diff --git a/app/actions/bundle.actions.js b/app/actions/bundle.actions.js index ff9ae1e283..6f31ece7df 100644 --- a/app/actions/bundle.actions.js +++ b/app/actions/bundle.actions.js @@ -5,11 +5,17 @@ import { List, Map } from 'immutable'; import throttledQueue from 'throttled-queue'; import { bundleConstants } from '../constants/bundle.constants'; import { bundleService } from '../services/bundle.service'; -import { updateSearchResultsForBundleId } from '../actions/bundleFilter.actions'; +import { updateSearchResultsForBundleId } from './bundleFilter.actions'; import { dblDotLocalService } from '../services/dbl_dot_local.service'; -import { bundleManageResourceActions } from '../actions/bundleManageResources.actions'; +// eslint-disable-next-line import/no-cycle +import { bundleManageResourceActions } from './bundleManageResources.actions'; import { workspaceHelpers } from '../helpers/workspaces.helpers'; import { browserWindowService } from '../services/browserWindow.service'; +import { + getAddedBundle, + getResourcePaths, + getStoredResourcePaths +} from '../helpers/bundle.helpers'; export const bundleActions = { fetchAll, @@ -33,15 +39,15 @@ export const bundleActions = { export default bundleActions; -export function updateBundle(bundleId, updateManifestResources = false) { - return async (dispatch) => { +export function updateBundle(bundleId) { + return async dispatch => { try { const rawBundle = await bundleService.fetchById(bundleId); if (!bundleService.apiBundleHasMetadata(rawBundle)) { // console.log(`Skipping updateBundle for ${bundleId}`); return; // hasn't downloaded metadata yet. (don't expect to be in our list) } - dispatch(updateOrAddBundle(rawBundle, updateManifestResources)); + dispatch(updateOrAddBundle(rawBundle)); } catch (error) { if (error.status === 404) { // this has been deleted. @@ -53,8 +59,10 @@ export function updateBundle(bundleId, updateManifestResources = false) { } function tryAddNewEntry(rawBundle) { - return (dispatch) => { - const { dbl: { parent, id: dblId } } = rawBundle; + return dispatch => { + const { + dbl: { parent, id: dblId } + } = rawBundle; if (parent && parent.dblId === dblId) { return; } @@ -83,45 +91,44 @@ function getFormBundleTreeErrors(acc, treeNode) { } const treeError = { field_issues: [], - document_issues: [ - [ - 'missing_instance', - 'requires at least one instance' - ] - ], + document_issues: [['missing_instance', 'requires at least one instance']], response_format_valid: true, response_valid: false }; // build formKey recusively from node.id -> parent.node.id const formKey = [...parents, this] - .filter(context => context.key && context.node.id && - !['contains', 'instances'].includes(context.key)) - .map(context => context.node.id).join('/'); + .filter( + context => + context.key && + context.node.id && + !['contains', 'instances'].includes(context.key) + ) + .map(context => context.node.id) + .join('/'); return { ...acc, [formKey]: treeError }; } async function getAllFormsErrorStatus(bundleId) { const formsErrorStatus = await bundleService.checkAllFields(bundleId); const formStructure = await bundleService.getFormBundleTree(bundleId); - const formTreeErrors = traverse(formStructure).reduce(getFormBundleTreeErrors, {}); + const formTreeErrors = traverse(formStructure).reduce( + getFormBundleTreeErrors, + {} + ); return { ...formsErrorStatus, ...formTreeErrors }; } -function updateOrAddBundle(rawBundle, updateManifestResources = false) { +function updateOrAddBundle(rawBundle) { return async (dispatch, getState) => { const { local_id: bundleId } = rawBundle; const addedBundle = getAddedBundle(getState, bundleId); - const hasStoredResources = bundleService.getHasStoredResources(rawBundle); - const manifestResources = (updateManifestResources || hasStoredResources || - (addedBundle && Object.keys(addedBundle.manifestResources || []).length)) ? - await bundleService.getManifestResourceDetails(bundleId) : {}; const { status } = bundleService.getInitialTaskAndStatus(rawBundle); - const formsErrorStatus = status === 'DRAFT' ? await getAllFormsErrorStatus(bundleId) : {}; - const resourceCountManifest = (Object.values(manifestResources) || []).length; + const formsErrorStatus = + status === 'DRAFT' ? await getAllFormsErrorStatus(bundleId) : {}; const bundle = await bundleService.convertApiBundleToNathanaelBundle( rawBundle, - { resourceCountManifest, formsErrorStatus, manifestResources } + { formsErrorStatus } ); if (addedBundle) { // console.log(`Updated bundle ${bundleId} from ${context}`); @@ -161,7 +168,10 @@ export function createDraftRevision(_bundleId) { function updateUploadJobs(bundleId, uploadJob, removeJobOrBundle) { return { - type: bundleConstants.UPDATE_UPLOAD_JOBS, bundleId, uploadJob, removeJobOrBundle + type: bundleConstants.UPDATE_UPLOAD_JOBS, + bundleId, + uploadJob, + removeJobOrBundle }; } @@ -209,7 +219,6 @@ export function forkIntoNewBundle(_bundleId, _medium) { } } - export function createNewBundle(_medium) { return async dispatch => { try { @@ -232,9 +241,17 @@ export function createNewBundle(_medium) { } /* should this move to bundleManagerResources.actions? */ -function bundleForEntryRevisionHasBeenMade(getState, dblIdTarget, revisionTarget) { - const { bundles: { allBundles } } = getState(); - const targetBundle = allBundles.find(b => b.dblId === dblIdTarget && b.revision === `${revisionTarget}`); +function bundleForEntryRevisionHasBeenMade( + getState, + dblIdTarget, + revisionTarget +) { + const { + bundles: { allBundles } + } = getState(); + const targetBundle = allBundles.find( + b => b.dblId === dblIdTarget && b.revision === `${revisionTarget}` + ); return targetBundle; } @@ -244,26 +261,34 @@ export function createBundleFromDBL(dblId, revision, license) { try { dispatch(request()); await dblDotLocalService.downloadMetadata(dblId, revision, license); - const targetBundle = - await waitUntil( - () => bundleForEntryRevisionHasBeenMade(getState, dblId, revision), - 60000, - 500 - ); + const targetBundle = await waitUntil( + () => bundleForEntryRevisionHasBeenMade(getState, dblId, revision), + 60000, + 500 + ); dispatch(success(targetBundle)); - dispatch(bundleManageResourceActions.getManifestResources(targetBundle.id)); + dispatch( + bundleManageResourceActions.getManifestResources(targetBundle.id) + ); } catch (error) { dispatch(failure(error)); } }; function request() { return { - type: bundleConstants.CREATE_FROM_DBL_REQUEST, dblId, revision, license + type: bundleConstants.CREATE_FROM_DBL_REQUEST, + dblId, + revision, + license }; } function success(targetBundle) { return { - type: bundleConstants.CREATE_FROM_DBL_SUCCESS, dblId, revision, license, targetBundle + type: bundleConstants.CREATE_FROM_DBL_SUCCESS, + dblId, + revision, + license, + targetBundle }; } function failure(error) { @@ -273,26 +298,30 @@ export function createBundleFromDBL(dblId, revision, license) { export function setupBundlesEventSource() { return (dispatch, getState) => { - const { authentication: { eventSource } } = getState(); + const { + authentication: { eventSource } + } = getState(); if (!eventSource) { console.error('EventSource undefined'); return; } const listeners = { - error: (e) => dispatch(listenError(e)), + error: e => dispatch(listenError(e)), 'storer/execute_task': listenStorerExecuteTaskDownloadResources, - 'storer/change_mode': (e) => dispatch(listenStorerChangeMode(e)), - 'uploader/job': (e) => dispatch(listenUploaderJob(e)), - 'uploader/createJob': (e) => listenUploaderCreateJob(e, dispatch), + 'storer/change_mode': e => dispatch(listenStorerChangeMode(e)), + 'uploader/job': e => dispatch(listenUploaderJob(e)), + 'uploader/createJob': e => listenUploaderCreateJob(e, dispatch), 'downloader/receiver': listenDownloaderReceiver, - 'downloader/spec_status': (e) => dispatch(listenDownloaderSpecStatus(e)), - 'downloader/global_status': (e) => dispatch(listenDownloaderGlobalStatus(e)), - 'uploader/global_status': (e) => dispatch(listenUploaderGlobalStatus(e)), - 'storer/delete_resource': (e) => listenStorerDeleteResource(e, dispatch, getState), - 'storer/delete_bundle': (e) => dispatch(listenStorerDeleteBundle(e)), - 'storer/write_resource': (e) => dispatch(listenStorerWriteResource(e)) + 'downloader/spec_status': e => dispatch(listenDownloaderSpecStatus(e)), + 'downloader/global_status': e => + dispatch(listenDownloaderGlobalStatus(e)), + 'uploader/global_status': e => dispatch(listenUploaderGlobalStatus(e)), + 'storer/delete_resource': e => + listenStorerDeleteResource(e, dispatch, getState), + 'storer/delete_bundle': e => dispatch(listenStorerDeleteBundle(e)), + 'storer/write_resource': e => dispatch(listenStorerWriteResource(e)) }; - Object.keys(listeners).forEach((evType) => { + Object.keys(listeners).forEach(evType => { const handler = listeners[evType]; eventSource.addEventListener(evType, handler); }); @@ -310,7 +339,11 @@ export function setupBundlesEventSource() { log.error(data); } return { - type: 'SSE_ERROR', dispatcher: 'bundle.actions', rawData, data, event + type: 'SSE_ERROR', + dispatcher: 'bundle.actions', + rawData, + data, + event }; } @@ -347,7 +380,7 @@ export function setupBundlesEventSource() { } function listenStorerWriteResource(event) { - return async (dispatch) => { + return async dispatch => { /* {'event': 'storer/write_resource', 'data': {'args': ('50501698-e832-4db5-8973-f85340dc2e39', 'metadata.xml'), @@ -385,7 +418,7 @@ export function setupBundlesEventSource() { */ function listenUploaderJob(e) { return (dispatch, getState) => { - const uploadJobs = getState().bundles.uploadJobs; + const { uploadJobs } = getState().bundles; const data = JSON.parse(e.data); const [type, ...nextArgs] = data.args; if (type === 'updated') { @@ -393,8 +426,19 @@ export function setupBundlesEventSource() { const bundleId = uploadJobs[jobId]; const addedBundle = getAddedBundle(getState, bundleId); if (addedBundle.mode === 'upload') { - const [resourceCountToUpload, resourceCountUploaded] = [payload[0], payload[5]]; - dispatch(updateUploadProgress(bundleId, entryId, jobId, resourceCountUploaded, resourceCountToUpload)); + const [resourceCountToUpload, resourceCountUploaded] = [ + payload[0], + payload[5] + ]; + dispatch( + updateUploadProgress( + bundleId, + entryId, + jobId, + resourceCountUploaded, + resourceCountToUpload + ) + ); } dispatch(fetchUploadQueueCounts()); return; @@ -410,11 +454,17 @@ export function setupBundlesEventSource() { return dispatch(updateUploadMessage(bundleId, jobId, payload)); } } - } + }; } - function updateUploadProgress(bundleId, entryId, jobId, resourceCountUploaded, resourceCountToUpload) { - return async (dispatch) => { + function updateUploadProgress( + bundleId, + entryId, + jobId, + resourceCountUploaded, + resourceCountToUpload + ) { + return async dispatch => { await bundleService.saveJobSpecToTempFolder(bundleId); return dispatch({ type: bundleConstants.UPLOAD_RESOURCES_UPDATE_PROGRESS, @@ -424,7 +474,7 @@ export function setupBundlesEventSource() { resourceCountUploaded, resourceCountToUpload }); - } + }; } function updateUploadMessage(bundleId, jobId, message) { @@ -459,7 +509,9 @@ export function setupBundlesEventSource() { if (!addedBundle) { return; // hasn't been added yet, so doesn't need to be updated. } - dispatch(updateDownloadStatus(bundleId, resourcesDownloaded, resourcesToDownload)); + dispatch( + updateDownloadStatus(bundleId, resourcesDownloaded, resourcesToDownload) + ); dispatch(updateSearchResultsForBundleId(bundleId)); dispatch(fetchDownloadQueueCounts()); }; @@ -497,13 +549,12 @@ export function setupBundlesEventSource() { const bundleId = data.args[0]; dispatch(removeBundleSuccess(bundleId)); dispatch(updateUploadJobs(bundleId, null, bundleId)); - await waitUntil( - () => !getAddedBundle(getState, bundleId), - 60000, - 500 - ); + await waitUntil(() => !getAddedBundle(getState, bundleId), 60000, 500); const gotState = getState(); - workspaceHelpers.persistStarredEntries(gotState, gotState.bundlesFilter.starredEntries); + workspaceHelpers.persistStarredEntries( + gotState, + gotState.bundlesFilter.starredEntries + ); }; } } @@ -511,14 +562,15 @@ export function setupBundlesEventSource() { const throttleAddBundle = throttledQueue(4, 1000, true); function addBundle(bundle, rawBundle) { - return dispatch => throttleAddBundle(() => { - dispatch({ - type: bundleConstants.ADD_BUNDLE, - bundle, - rawBundle + return dispatch => + throttleAddBundle(() => { + dispatch({ + type: bundleConstants.ADD_BUNDLE, + bundle, + rawBundle + }); + dispatch(updateSearchResultsForBundleId(bundle.id)); }); - dispatch(updateSearchResultsForBundleId(bundle.id)); - }); } function isInDraftMode(bundle) { @@ -529,10 +581,16 @@ export function removeExcessBundles() { return (dispatch, getState) => { const { bundles } = getState(); const { addedByBundleIds, items } = bundles; - const itemsByBundleIds = List(items).map(bundle => bundle.id).toSet(); - const itemsByParentIds = List(items).filter(b => b.parent).reduce((acc, bundle) => - acc.set(bundle.parent.bundleId, bundle), Map()); - const itemsByDblId = items.reduce((acc, bundle) => ({ ...acc, [bundle.dblId]: bundle }), {}); + const itemsByBundleIds = List(items) + .map(bundle => bundle.id) + .toSet(); + const itemsByParentIds = List(items) + .filter(b => b.parent) + .reduce((acc, bundle) => acc.set(bundle.parent.bundleId, bundle), Map()); + const itemsByDblId = items.reduce( + (acc, bundle) => ({ ...acc, [bundle.dblId]: bundle }), + {} + ); const bundleIdsToRemove = Object.keys(addedByBundleIds).filter(addedId => { if (itemsByBundleIds.includes(addedId)) { return false; @@ -560,20 +618,20 @@ export function removeExcessBundles() { return true; }); console.log(`Deleting ${bundleIdsToRemove.length} empty/unused revisions`); - bundleIdsToRemove.forEach((idBundleToRemove) => { + bundleIdsToRemove.forEach(idBundleToRemove => { dispatch(removeBundle(idBundleToRemove)); }); }; } function updateDownloadQueue(nSpecs, nAtoms) { - return (dispatch) => { + return dispatch => { dispatch({ type: bundleConstants.UPDATE_DOWNLOAD_QUEUE, nSpecs, nAtoms }); }; } function updateUploadQueue(nSpecs, nAtoms) { - return (dispatch) => { + return dispatch => { dispatch({ type: bundleConstants.UPDATE_UPLOAD_QUEUE, nSpecs, nAtoms }); }; } @@ -583,7 +641,10 @@ export function fetchDownloadQueueCounts() { try { const downloadQueueList = await bundleService.getSubsystemDownloadQueue(); const nSpecs = Object.keys(downloadQueueList).length; - const nAtoms = downloadQueueList.reduce((acc, spec) => acc + (spec.n_atoms - spec.n_downloaded), 0); + const nAtoms = downloadQueueList.reduce( + (acc, spec) => acc + (spec.n_atoms - spec.n_downloaded), + 0 + ); return dispatch(updateDownloadQueue(nSpecs, nAtoms)); } catch (error) { log.error(error); @@ -596,7 +657,10 @@ export function fetchUploadQueueCounts() { try { const uploadQueueList = await bundleService.getSubsystemUploadQueue(); const nSpecs = Object.keys(uploadQueueList).length; - const nAtoms = uploadQueueList.reduce((acc, spec) => acc + (spec.n_atoms - spec.n_uploaded), 0); + const nAtoms = uploadQueueList.reduce( + (acc, spec) => acc + (spec.n_atoms - spec.n_uploaded), + 0 + ); return dispatch(updateUploadQueue(nSpecs, nAtoms)); } catch (error) { log.error(error); @@ -604,14 +668,6 @@ export function fetchUploadQueueCounts() { }; } -function getAddedBundle(getState, bundleId) { - const { bundles } = getState(); - const { addedByBundleIds = {} } = bundles; - const addedBundles = addedByBundleIds[bundleId]; - return addedBundles; -} - - export function uploadBundle(id) { return async dispatch => { try { @@ -632,7 +688,7 @@ export function uploadBundle(id) { } export function openJobSpecInBrowser(bundleId) { - return async (dispatch) => { + return async dispatch => { const jobSpecFile = await bundleService.saveJobSpecToTempFolder(bundleId); browserWindowService.openFileInChromeBrowser(jobSpecFile, false); dispatch({ type: 'BUNDLE_OPEN_JOB_SPEC', jobSpecFile }); @@ -640,9 +696,9 @@ export function openJobSpecInBrowser(bundleId) { } export function downloadResources(_id, _uris = []) { - return async dispatch => { + return async (dispatch, getState) => { try { - const manifestResourcePaths = await bundleService.getManifestResourcePaths(_id); + const manifestResourcePaths = getResourcePaths(getState, _id); dispatch(request(_id, manifestResourcePaths, _uris)); dispatch(updateSearchResultsForBundleId(_id)); await bundleService.downloadResources(_id, _uris); @@ -652,7 +708,12 @@ export function downloadResources(_id, _uris = []) { } }; function request(id, manifestResourcePaths, uris) { - return { type: bundleConstants.DOWNLOAD_RESOURCES_REQUEST, id, manifestResourcePaths, uris }; + return { + type: bundleConstants.DOWNLOAD_RESOURCES_REQUEST, + id, + manifestResourcePaths, + uris + }; } function failure(id, error) { return { type: bundleConstants.DOWNLOAD_RESOURCES_FAILURE, id, error }; @@ -660,11 +721,12 @@ export function downloadResources(_id, _uris = []) { } export function removeResources(id, selected = []) { - return async (dispatch) => { + return async (dispatch, getState) => { try { - const resourcePaths = await bundleService.getResourcePaths(id); - const resourcePathsToRemove = resourcePaths - .filter(path => !selected.length || selected.includes(path)); + const resourcePaths = getStoredResourcePaths(getState, id); + const resourcePathsToRemove = resourcePaths.filter( + path => !selected.length || selected.includes(path) + ); dispatch(request(id, resourcePathsToRemove)); dispatch(updateSearchResultsForBundleId(id)); await bundleService.removeResources(id, resourcePathsToRemove); @@ -674,7 +736,11 @@ export function removeResources(id, selected = []) { } }; function request(_id, resourcesToRemove) { - return { type: bundleConstants.REMOVE_RESOURCES_REQUEST, id: _id, resourcesToRemove }; + return { + type: bundleConstants.REMOVE_RESOURCES_REQUEST, + id: _id, + resourcesToRemove + }; } function failure(_id, error) { return { type: bundleConstants.REMOVE_RESOURCES_FAILURE, id, error }; @@ -704,16 +770,22 @@ function removeBundleSuccess(id) { return (dispatch, getState) => { const deletedBundle = getAddedBundle(getState, id); dispatch({ - type: bundleConstants.DELETE_SUCCESS, id, appStateSnapshot: getState(), deletedBundle + type: bundleConstants.DELETE_SUCCESS, + id, + appStateSnapshot: getState(), + deletedBundle }); }; } export function requestSaveBundleTo(id, selectedFolder) { - return async dispatch => { + return async (dispatch, getState) => { const bundleInfo = await bundleService.fetchById(id); - const bundleBytesToSave = traverse(bundleInfo.store.file_info).reduce(addByteSize, 0); - const resourcePaths = await bundleService.getResourcePaths(id); + const bundleBytesToSave = traverse(bundleInfo.store.file_info).reduce( + addByteSize, + 0 + ); + const resourcePaths = getStoredResourcePaths(getState, id); resourcePaths.unshift('metadata.xml'); const resourcePathsProgress = resourcePaths.reduce((acc, resourcePath) => { acc[resourcePath] = 0; @@ -729,9 +801,11 @@ export function requestSaveBundleTo(id, selectedFolder) { id, resourcePath, (resourceTotalBytesSaved, resourceProgress) => { - const originalResourceBytesTransferred = resourcePathsProgress[resourcePath]; + const originalResourceBytesTransferred = + resourcePathsProgress[resourcePath]; resourcePathsProgress[resourcePath] = resourceTotalBytesSaved; - const bytesDiff = resourceTotalBytesSaved - originalResourceBytesTransferred; + const bytesDiff = + resourceTotalBytesSaved - originalResourceBytesTransferred; bundleBytesSaved += bytesDiff; if (resourceProgress && resourceProgress % 100 === 0) { const updatedArgs = { @@ -777,7 +851,7 @@ export function requestSaveBundleTo(id, selectedFolder) { resourcePath, resourceTotalBytesSaved, bundleBytesSaved, - bundleBytesToSave, + bundleBytesToSave }) { return { type: bundleConstants.SAVETO_UPDATED, @@ -814,7 +888,9 @@ export function selectBundleEntryRevision(bundle) { export function getEntryRevisions(bundleId) { return async (dispatch, getState) => { - const { bundles: { addedByBundleIds } } = getState(); + const { + bundles: { addedByBundleIds } + } = getState(); const bundle = addedByBundleIds[bundleId]; const { dblId } = bundle; const entryRevisions = await dblDotLocalService.getEntryRevisions(dblId); diff --git a/app/actions/bundleManageResources.actions.js b/app/actions/bundleManageResources.actions.js index 02e4899f58..6462d3a2da 100644 --- a/app/actions/bundleManageResources.actions.js +++ b/app/actions/bundleManageResources.actions.js @@ -10,6 +10,7 @@ import { dblDotLocalService } from '../services/dbl_dot_local.service'; import { utilities } from '../utils/utilities'; import { openEditMetadata, saveMetadatFileToTempBundleFolder } from './bundleEditMetadata.actions'; import { bundleActions } from './bundle.actions'; +import { getResourcesDetails } from '../helpers/bundle.helpers'; export const bundleManageResourceActions = { openResourceManager, @@ -25,7 +26,7 @@ export const bundleManageResourceActions = { export function openResourceManager(_bundleId, _mode) { return async (dispatch, getState) => { await bundleService.waitStopCreateMode(_bundleId); - dispatch(bundleActions.updateBundle(_bundleId, true)); + dispatch(bundleActions.updateBundle(_bundleId)); const { addedByBundleIds } = getState().bundles; const bundleId = _bundleId; const bundle = addedByBundleIds[bundleId]; @@ -66,7 +67,7 @@ export function getManifestResources(_bundleId) { return async dispatch => { try { dispatch(request(_bundleId)); - const manifestResources = await bundleService.getManifestResourceDetails(_bundleId); + const manifestResources = getResourcesDetails(_bundleId); const rawBundle = await bundleService.fetchById(_bundleId); const storedFiles = bundleService.getFlatFileInfo(rawBundle); dispatch(success(_bundleId, manifestResources, storedFiles)); diff --git a/app/components/DBLEntryRow.js b/app/components/DBLEntryRow.js index 7690f4ca84..091aed2232 100644 --- a/app/components/DBLEntryRow.js +++ b/app/components/DBLEntryRow.js @@ -28,8 +28,16 @@ import InfoIcon from '@material-ui/icons/Info'; import styles from './DBLEntryRow.css'; import ControlledHighlighter from './ControlledHighlighter'; import { toggleEntryStar } from '../actions/bundleFilter.actions'; -import { toggleSelectEntry, requestSaveBundleTo, forkIntoNewBundle, - downloadResources, uploadBundle, updateBundle, createDraftRevision, openJobSpecInBrowser } from '../actions/bundle.actions'; +import { + toggleSelectEntry, + requestSaveBundleTo, + forkIntoNewBundle, + downloadResources, + uploadBundle, + updateBundle, + createDraftRevision, + openJobSpecInBrowser +} from '../actions/bundle.actions'; import { openEditMetadata } from '../actions/bundleEditMetadata.actions'; import editMetadataService from '../services/editMetadata.service'; import { openResourceManager } from '../actions/bundleManageResources.actions'; @@ -53,6 +61,7 @@ type Props = { status: string, medium: string, displayAs: {}, + mode: string, resourceCountStored?: number, resourceCountManifest?: ?number, bundleMatches: {}, @@ -72,72 +81,81 @@ type Props = { newMediaTypes: [], toggleSelectEntry: () => {}, downloadResources: () => {}, - openResourceManager: () => {}, - requestSaveBundleTo: () => {}, - forkIntoNewBundle: () => {}, - openEditMetadata: () => {}, - uploadBundle: () => {}, - updateBundle: () => {}, - createDraftRevision: () => {}, - openJobSpecInBrowser: () => {}, - toggleEntryStar: () => {} + openEntryResourceManager: () => {}, + requestSaveEntryBundleTo: () => {}, + forkEntryIntoNewBundle: () => {}, + openEntryEditMetadata: () => {}, + uploadEntryBundle: () => {}, + updateEntryBundle: () => {}, + createEntryDraftRevision: () => {}, + openEntryJobSpecInBrowser: () => {}, + toggleEntryStarBtn: () => {} }; const mapDispatchToProps = { toggleSelectEntry, downloadResources, - openResourceManager, - requestSaveBundleTo, - forkIntoNewBundle, - openEditMetadata, - uploadBundle, - updateBundle, - createDraftRevision, - openJobSpecInBrowser, - toggleEntryStar + openEntryResourceManager: openResourceManager, + requestSaveEntryBundleTo: requestSaveBundleTo, + forkEntryIntoNewBundle: forkIntoNewBundle, + openEntryEditMetadata: openEditMetadata, + uploadEntryBundle: uploadBundle, + updateEntryBundle: updateBundle, + createEntryDraftRevision: createDraftRevision, + openEntryJobSpecInBrowser: openJobSpecInBrowser, + toggleEntryStarBtn: toggleEntryStar }; const getTask = (state, props) => props.task; const getStatus = (state, props) => props.status; -const getIsSearchActive = (state) => state.bundlesFilter.isSearchActive; -const getStarredEntries = (state) => state.bundlesFilter.starredEntries; +const getIsSearchActive = state => state.bundlesFilter.isSearchActive; +const getStarredEntries = state => state.bundlesFilter.starredEntries; const emptyBundleMatches = emptyObject; const getEmptryBundleMatches = () => emptyBundleMatches; const getBundleId = (state, props) => props.bundleId; const getDblId = (state, props) => props.dblId; const getBundleMatches = (state, props) => - (state.bundlesFilter.searchResults && state.bundlesFilter.searchResults.bundlesMatching ? - (state.bundlesFilter.searchResults.bundlesMatching[props.bundleId] || emptyBundleMatches) - : emptyBundleMatches); - -const makeGetIsDownloading = () => createSelector( - [getTask, getStatus], - (task, status) => (task === 'DOWNLOAD' && status === 'IN_PROGRESS') -); + state.bundlesFilter.searchResults && + state.bundlesFilter.searchResults.bundlesMatching + ? state.bundlesFilter.searchResults.bundlesMatching[props.bundleId] || + emptyBundleMatches + : emptyBundleMatches; + +const makeGetIsDownloading = () => + createSelector( + [getTask, getStatus], + (task, status) => task === 'DOWNLOAD' && status === 'IN_PROGRESS' + ); -const makeShouldShowRow = () => createSelector( - [getIsSearchActive, getBundleMatches], - (isActiveSearch, bundleMatches) => !isActiveSearch || Object.keys(bundleMatches).length > 0 -); +const makeShouldShowRow = () => + createSelector( + [getIsSearchActive, getBundleMatches], + (isActiveSearch, bundleMatches) => + !isActiveSearch || Object.keys(bundleMatches).length > 0 + ); -const makeGetBundleMatches = () => createSelector( - [getIsSearchActive, getBundleMatches, getEmptryBundleMatches], - (isActiveSearch, bundleMatches, emptyMatches) => (isActiveSearch ? bundleMatches : emptyMatches) -); +const makeGetBundleMatches = () => + createSelector( + [getIsSearchActive, getBundleMatches, getEmptryBundleMatches], + (isActiveSearch, bundleMatches, emptyMatches) => + isActiveSearch ? bundleMatches : emptyMatches + ); -const getRequestingRevision = (state) => state.bundleEditMetadata.requestingRevision; +const getRequestingRevision = state => + state.bundleEditMetadata.requestingRevision; -const makeGetIsRequestingRevision = () => createSelector( - [getRequestingRevision, getBundleId], - (requestingRevision, bundleId) => (requestingRevision === bundleId) -); +const makeGetIsRequestingRevision = () => + createSelector( + [getRequestingRevision, getBundleId], + (requestingRevision, bundleId) => requestingRevision === bundleId + ); const getSelectedBundleEntryRevisions = state => state.bundles.selectedBundleEntryRevisions || emptyObject; const getSelectedBundleEntryRevision = (state, props) => getSelectedBundleEntryRevisions(state)[props.dblId]; -const getAllBundles = (state) => state.bundles.allBundles || emptyObject; +const getAllBundles = state => state.bundles.allBundles || emptyObject; const getRevision = (state, props) => props.revision; const getParent = (state, props) => props.parent; @@ -146,7 +164,11 @@ function filterForLaterRevisionsOrDrafts(bundleId, effectiveRevision) { if (b.id === bundleId) { return false; } - const testEffectiveRevision = bundleService.getRevisionOrParentRevision(b.dblId, b.revision, b.parent); + const testEffectiveRevision = bundleService.getRevisionOrParentRevision( + b.dblId, + b.revision, + b.parent + ); if (b.revision !== '0' && testEffectiveRevision <= effectiveRevision) { return false; } @@ -154,23 +176,45 @@ function filterForLaterRevisionsOrDrafts(bundleId, effectiveRevision) { }; } -const makeGetLaterEntryRevisions = () => createSelector( - [getSelectedBundleEntryRevision, getAllBundles, getBundleId, getDblId, getRevision, getParent], - (selectedBundleEntryRevision, allBundles, bundleId, dblId, revision, parent) => { - if (!selectedBundleEntryRevision) { - return emptyArray; // todo: remove this optimization if (it doesn't effect initial downloads) +const makeGetLaterEntryRevisions = () => + createSelector( + [ + getSelectedBundleEntryRevision, + getAllBundles, + getBundleId, + getDblId, + getRevision, + getParent + ], + ( + selectedBundleEntryRevision, + allBundles, + bundleId, + dblId, + revision, + parent + ) => { + if (!selectedBundleEntryRevision) { + return emptyArray; // todo: remove this optimization if (it doesn't effect initial downloads) + } + const effectiveRevision = bundleService.getRevisionOrParentRevision( + dblId, + revision, + parent + ); + const allRevisions = allBundles.filter(b => b.dblId === dblId); + const laterRevisions = allRevisions.filter( + filterForLaterRevisionsOrDrafts(bundleId, effectiveRevision) + ); + return laterRevisions; } - const effectiveRevision = bundleService.getRevisionOrParentRevision(dblId, revision, parent); - const allRevisions = allBundles.filter(b => b.dblId === dblId); - const laterRevisions = allRevisions.filter(filterForLaterRevisionsOrDrafts(bundleId, effectiveRevision)); - return laterRevisions; - } -); + ); -const makeGetIsEntryStarred = () => createSelector( - [getStarredEntries, getDblId], - (starredEntries, dblId) => (starredEntries || Set()).has(dblId) -); +const makeGetIsEntryStarred = () => + createSelector( + [getStarredEntries, getDblId], + (starredEntries, dblId) => (starredEntries || Set()).has(dblId) + ); const makeMapStateToProps = () => { const shouldShowRow = makeShouldShowRow(); @@ -181,7 +225,10 @@ const makeMapStateToProps = () => { const getFormsErrors = editMetadataService.makeGetFormsErrors(); const getLaterEntryRevisions = makeGetLaterEntryRevisions(); const mapStateToProps = (state, props) => { - const { bundlesSaveTo, bundles: { newMediaTypes = emptyArray } } = state; + const { + bundlesSaveTo, + bundles: { newMediaTypes = emptyArray } + } = state; return { isRequestingRevision: getIsRequestingRevision(state, props), laterEntryRevisions: getLaterEntryRevisions(state, props), @@ -200,186 +247,215 @@ const makeMapStateToProps = () => { class DBLEntryRow extends PureComponent { props: Props; + state = { anchorEl: null - } + }; componentDidMount() { const { - resourceCountManifest, resourceCountStored, status, formsErrorStatus + status, + formsErrorStatus, + updateEntryBundle, + bundleId } = this.props; - if ((resourceCountManifest === null && resourceCountStored) || - (status === 'DRAFT' && Object.keys(formsErrorStatus).length === 0)) { - this.props.updateBundle(this.props.bundleId); + if (status === 'DRAFT' && Object.keys(formsErrorStatus).length === 0) { + updateEntryBundle(bundleId); } } componentWillReceiveProps(nextProps) { - if (this.props.task === 'SAVETO' && nextProps.task !== 'SAVETO') { + const { task } = this.props; + if (task === 'SAVETO' && nextProps.task !== 'SAVETO') { this.openInFolder(); } - // recompute manifest count for drafts if we have changed resource count - if ((nextProps.resourceCountManifest === null && nextProps.resourceCountStored) || - (nextProps.status === 'DRAFT' && - (this.props.resourceCountStored !== nextProps.resourceCountStored || - Object.keys(nextProps.formsErrorStatus).length === 0))) { - this.props.updateBundle(this.props.bundleId); - } } - onKeyPress = (event) => { + onKeyPress = event => { if (['Enter', ' '].includes(event.key)) { this.onClickBundleRow(); } console.log(event.key); - } + }; onClickBundleRow = () => { - const { bundleId: id, dblId, displayAs } = this.props; - this.props.toggleSelectEntry({ id, dblId, displayAs }); - } + const { + bundleId: id, + dblId, + displayAs, + toggleSelectEntry: toggleSelectedEntry + } = this.props; + toggleSelectedEntry({ id, dblId, displayAs }); + }; - handleClickStar = (event) => { - const { dblId } = this.props; + handleClickStar = event => { + const { dblId, toggleEntryStarBtn } = this.props; event.stopPropagation(); - this.props.toggleEntryStar(dblId); - } + toggleEntryStarBtn(dblId); + }; showStatusAsText = () => { if (this.getIsUploading()) { return false; } const { status } = this.props; - return (['IN_PROGRESS'].includes(status)); - } + return ['IN_PROGRESS'].includes(status); + }; showStoredButton = () => { const { task, status } = this.props; - return ((task === 'DOWNLOAD' && status === 'COMPLETED') - || status === 'DRAFT'); - } + return ( + (task === 'DOWNLOAD' && status === 'COMPLETED') || status === 'DRAFT' + ); + }; showDownloadButton = () => { const { task, status } = this.props; - return (task === 'DOWNLOAD' && status === 'NOT_STARTED'); - } + return task === 'DOWNLOAD' && status === 'NOT_STARTED'; + }; hasNoStoredResources = () => { const { resourceCountStored = 0 } = this.props; return resourceCountStored === 0; - } + }; shouldDisableCleanResources = () => - (this.hasNoStoredResources() || this.shouldDisableDraftRevisionOrEdit()); + this.hasNoStoredResources() || this.shouldDisableDraftRevisionOrEdit(); shouldDisableSaveTo = () => this.shouldDisableCleanResources(); getIsUploading = () => { const { isUploading = false, task, status } = this.props; return isUploading || (task === 'UPLOAD' && status === 'IN_PROGRESS'); - } + }; shouldShowUpload = () => { const { status } = this.props; return status === 'DRAFT' || this.getIsUploading(); - } + }; + + shouldShowDraftRevision = () => { + const { status, license } = this.props; + return status !== 'DRAFT' && license === 'owned'; + }; - shouldShowDraftRevision = () => (this.props.status !== 'DRAFT' && this.props.license === 'owned'); - shouldShowSaveAsNew = () => (this.props.status !== 'DRAFT'); - shouldShowEdit = () => (this.props.status === 'DRAFT' && this.props.license === 'owned'); + shouldShowSaveAsNew = () => { + const { status } = this.props; + return status !== 'DRAFT'; + }; + + shouldShowEdit = () => { + const { status, license } = this.props; + return status === 'DRAFT' && license === 'owned'; + }; isNewDraftEntry = () => { - const { - status, revision, parent, dblId - } = this.props; - return status === 'DRAFT' && bundleService.getRevisionOrParentRevision(dblId, revision, parent) === 0; - } + const { status, revision, parent, dblId } = this.props; + return ( + status === 'DRAFT' && + bundleService.getRevisionOrParentRevision(dblId, revision, parent) === 0 + ); + }; - shouldDisableRevise = () => (this.props.isRequestingRevision || this.props.isDownloading) + shouldDisableRevise = () => { + const { isRequestingRevision, isDownloading } = this.props; + return isRequestingRevision || isDownloading; + }; - shouldDisableUpload = () => (this.shouldDisableDraftRevisionOrEdit() || - Object.keys(this.props.formsErrors).length > 0 || (this.isNewDraftEntry() && this.props.resourceCountStored === 0)); + shouldDisableUpload = () => { + const { formsErrors, resourceCountStored } = this.props; + return ( + this.shouldDisableDraftRevisionOrEdit() || + Object.keys(formsErrors).length > 0 || + (this.isNewDraftEntry() && resourceCountStored === 0) + ); + }; shouldDisableDraftRevisionOrEdit = () => { return this.getIsUploading() || this.shouldDisableRevise(); - } + }; emptyMatches = emptyArray; - getMatches = (textToHighlight) => { + getMatches = textToHighlight => { const { bundleMatches } = this.props; const matches = bundleMatches[textToHighlight] || this.emptyMatches; return matches; - } + }; - getHighlighterSharedProps = (textToHighlight) => ({ + getHighlighterSharedProps = textToHighlight => ({ textToHighlight, matches: this.getMatches(textToHighlight) - }) + }); - onClickManageResources = (mode) => (event) => { - const { bundleId } = this.props; - this.props.openResourceManager(bundleId, mode, true); + onClickManageResources = mode => event => { + const { bundleId, openEntryResourceManager } = this.props; + openEntryResourceManager(bundleId, mode, true); event.stopPropagation(); - } + }; - onClickEditMetadata = (event) => { - const { bundleId } = this.props; - this.props.openEditMetadata(bundleId, undefined, true); + onClickEditMetadata = event => { + const { bundleId, openEntryEditMetadata } = this.props; + openEntryEditMetadata(bundleId, undefined, true); event.stopPropagation(); - } + }; - onClickDraftRevision = (event) => { - const { bundleId } = this.props; - this.props.createDraftRevision(bundleId); + onClickDraftRevision = event => { + const { bundleId, createEntryDraftRevision } = this.props; + createEntryDraftRevision(bundleId); event.stopPropagation(); - } + }; onClickForkNewEntry = event => { this.setState({ anchorEl: event.currentTarget }); event.stopPropagation(); }; - handleCloseMediaTypeMenu = (event) => { + handleCloseMediaTypeMenu = event => { this.setState({ anchorEl: null }); event.stopPropagation(); }; - handleClickMediaType = (medium) => (event) => { - const { bundleId } = this.props; - this.props.forkIntoNewBundle(bundleId, medium); + handleClickMediaType = medium => event => { + const { bundleId, forkEntryIntoNewBundle } = this.props; + forkEntryIntoNewBundle(bundleId, medium); this.handleCloseMediaTypeMenu(event); event.stopPropagation(); }; handleClickUploadInfo = () => { - const { bundleId } = this.props; - this.props.openJobSpecInBrowser(bundleId); - } + const { bundleId, openEntryJobSpecInBrowser } = this.props; + openEntryJobSpecInBrowser(bundleId); + }; - onClickUploadBundle = (event) => { - const { bundleId } = this.props; - this.props.uploadBundle(bundleId); + onClickUploadBundle = event => { + const { bundleId, uploadEntryBundle } = this.props; + uploadEntryBundle(bundleId); event.stopPropagation(); - } + }; - startSaveBundleTo = (event) => { - const { bundlesSaveTo, bundleId } = this.props; + startSaveBundleTo = event => { + const { bundlesSaveTo, bundleId, requestSaveEntryBundleTo } = this.props; const { savedToHistory } = bundlesSaveTo; stopPropagation(event); const bundleSavedToInfo = getBundleExportInfo(bundleId, savedToHistory); - const defaultPath = bundleSavedToInfo ? bundleSavedToInfo.folderName : app.getPath('downloads'); - dialog.showOpenDialog({ - defaultPath, - properties: ['openDirectory'] - }, (folderName) => { - if (!folderName) { - return; // canceled. + const defaultPath = bundleSavedToInfo + ? bundleSavedToInfo.folderName + : app.getPath('downloads'); + dialog.showOpenDialog( + { + defaultPath, + properties: ['openDirectory'] + }, + folderName => { + if (!folderName) { + return; // canceled. + } + console.log(folderName.toString()); + requestSaveEntryBundleTo(bundleId, folderName.toString()); } - console.log(folderName.toString()); - this.props.requestSaveBundleTo(bundleId, folderName.toString()); - }); - } + ); + }; openInFolder = () => { const { bundlesSaveTo, bundleId } = this.props; @@ -389,55 +465,97 @@ class DBLEntryRow extends PureComponent { const { folderName } = bundleSavedToInfo; shell.openItem(folderName); } - } + }; - renderStatus = () => ( - - ); + renderStatus = () => { + const { displayAs } = this.props; + return ( + + ); + }; renderEditIcon = () => { const { status, classes, formsErrors } = this.props; const formsErrorCount = Object.keys(formsErrors).length; return [ - ux.conditionallyRenderBadge({ className: classes.badge, color: 'error' }, formsErrorCount, ), + ux.conditionallyRenderBadge( + { className: classes.badge, color: 'error' }, + formsErrorCount, + + ), status === 'DRAFT' ? 'Edit' : 'View' ]; }; - pickBackgroundColor = (isForRow) => { - const { - classes, status, revision, parent, dblId, mode - } = this.props; - return ux.getDblRowBackgroundColor(isForRow, classes, status, revision, parent, dblId, mode); - } + pickBackgroundColor = isForRow => { + const { classes, status, revision, parent, dblId, mode } = this.props; + return ux.getDblRowBackgroundColor( + isForRow, + classes, + status, + revision, + parent, + dblId, + mode + ); + }; - renderLicenseIcon = (license) => { + renderLicenseIcon = license => { const { classes } = this.props; if (license === 'owned') { - return ; + return ( + + ); } if (license === 'open-access') { - return ; + return ( + + ); } - return ; - } + return ( + + ); + }; render() { const { - bundleId, dblId, revision, medium, status, license, - displayAs, progress, - isSelected, shouldShowRow, isStarred, shouldShowStarred, + bundleId, + dblId, + revision, + medium, + status, + license, + displayAs, + progress, + isSelected, + shouldShowRow, + isStarred, + shouldShowStarred, classes, - newMediaTypes + newMediaTypes, + laterEntryRevisions } = this.props; const { anchorEl } = this.state; if (!shouldShowRow || (shouldShowStarred && !isStarred)) { - return (null); + return null; } const isUploading = this.getIsUploading(); const resourceManagerMode = status === 'DRAFT' ? 'addFiles' : 'download'; - const laterEntryRevisionsCount = this.props.laterEntryRevisions.length; - const laterRevisionsBadge = laterEntryRevisionsCount ? `${laterEntryRevisionsCount}+` : ''; + const laterEntryRevisionsCount = laterEntryRevisions.length; + const laterRevisionsBadge = laterEntryRevisionsCount + ? `${laterEntryRevisionsCount}+` + : ''; const mediumIconProps = { style: { marginRight: '0px' } }; return (
{ role="button" style={{ borderBottom: '1px solid lightgray' }} > - + - @@ -471,17 +599,26 @@ class DBLEntryRow extends PureComponent {
- +
- + - + @@ -492,14 +629,23 @@ class DBLEntryRow extends PureComponent { @@ -508,15 +654,21 @@ class DBLEntryRow extends PureComponent {
{this.renderLicenseIcon(license)} - +
- - + +
@@ -526,30 +678,63 @@ class DBLEntryRow extends PureComponent { )}
- {isUploading && + {isUploading && ( - } + )} {this.showStatusAsText() && (
- {} + { + + }
)} {this.showDownloadButton() && ( @@ -560,103 +745,136 @@ class DBLEntryRow extends PureComponent { onKeyPress={this.onClickManageResources('download')} onClick={this.onClickManageResources('download')} > - - + + )} - {status === 'IN_PROGRESS' && ()} + {status === 'IN_PROGRESS' && ( + + )} {isSelected && ( - + { } - {this.shouldShowDraftRevision() && - } - {this.shouldShowSaveAsNew() && -
+ + } + {this.shouldShowDraftRevision() && ( - - {newMediaTypes.map(mediumOption => ( - - {} - {mediumOption} - - ))} - -
} - + + {newMediaTypes.map(mediumOption => ( + + {} + {mediumOption} + + ))} + +
+ )} + - - {this.shouldShowUpload() && - + {this.shouldShowUpload() && ( + - + Upload - } + )} - )} + )} ); } @@ -677,7 +895,7 @@ export default compose( connect( makeMapStateToProps, mapDispatchToProps - ), + ) )(DBLEntryRow); function getBundleExportInfo(bundleId, savedToHistory) { diff --git a/app/components/EntryDrawer.js b/app/components/EntryDrawer.js index 4dd182e7e3..b03bfb5356 100644 --- a/app/components/EntryDrawer.js +++ b/app/components/EntryDrawer.js @@ -12,41 +12,42 @@ import ListItem from '@material-ui/core/ListItem'; import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemText from '@material-ui/core/ListItemText'; import OpenInNew from '@material-ui/icons/OpenInNew'; -import { openMetadataFile, openEditMetadata } from '../actions/bundleEditMetadata.actions'; +import { + openMetadataFile, + openEditMetadata +} from '../actions/bundleEditMetadata.actions'; import { openResourceManager } from '../actions/bundleManageResources.actions'; import { openEntryReports } from '../actions/report.actions'; import { closeEntryDrawer } from '../actions/entryAppBar.actions'; import { ux } from '../utils/ux'; - type Props = { classes: {}, theme: {}, bundleId: string, activeBundle: {}, openDrawer: boolean, - closeEntryDrawer: () => {}, - openMetadataFile: () => {}, - openEditMetadata: () => {}, - openResourceManager: () => {}, - openEntryReports: () => {} + hideEntryDrawer: () => {}, + openEntryMetadataFile: () => {}, + openEditEntryMetadata: () => {}, + openEntryResourceManager: () => {}, + switchToEntryReports: () => {} }; - function mapStateToProps(state, props) { const { id: bundleId } = props.activeBundle; return { bundleId, - openDrawer: state.entryAppBar.openDrawer, + openDrawer: state.entryAppBar.openDrawer }; } const mapDispatchToProps = { - openMetadataFile, - openEditMetadata, - openResourceManager, - closeEntryDrawer, - openEntryReports + openEntryMetadataFile: openMetadataFile, + openEditEntryMetadata: openEditMetadata, + openEntryResourceManager: openResourceManager, + hideEntryDrawer: closeEntryDrawer, + switchToEntryReports: openEntryReports }; const materialStyles = theme => ({ @@ -55,7 +56,6 @@ const materialStyles = theme => ({ ...ux.getEntryUxStyles(theme) }); - class EntryDrawer extends PureComponent { props: Props; @@ -64,34 +64,32 @@ class EntryDrawer extends PureComponent { const { status } = activeBundle; const mode = status === 'DRAFT' ? 'addFiles' : 'download'; return mode; - } - - getDrawerItems = () => ( - [ - { - label: 'Metadata', - icon: ux.getModeIcon('metadata'), - handleClick: this.handleSwitchToMetadata - }, - { - label: 'Resources', - icon: ux.getModeIcon(this.getResourceMode()), - handleClick: this.handleSwitchToResources - }, - { - label: 'Revisions', - icon: ux.getModeIcon('revisions'), - handleClick: this.handleSwitchToRevisions - }, - { - label: 'Reports', - icon: ux.getModeIcon('reports'), - handleClick: this.handleSwitchToReports - }, - ] - ); + }; - renderListItem = (item) => ( + getDrawerItems = () => [ + { + label: 'Metadata', + icon: ux.getModeIcon('metadata'), + handleClick: this.handleSwitchToMetadata + }, + { + label: 'Resources', + icon: ux.getModeIcon(this.getResourceMode()), + handleClick: this.handleSwitchToResources + }, + { + label: 'Revisions', + icon: ux.getModeIcon('revisions'), + handleClick: this.handleSwitchToRevisions + }, + { + label: 'Reports', + icon: ux.getModeIcon('reports'), + handleClick: this.handleSwitchToReports + } + ]; + + renderListItem = item => ( {item.icon} @@ -99,35 +97,35 @@ class EntryDrawer extends PureComponent { ); handleOpenMetadataXml = () => { - this.props.openMetadataFile(this.props.bundleId); - } + const { openEntryMetadataFile, bundleId } = this.props; + openEntryMetadataFile(bundleId); + }; handleSwitchToMetadata = () => { - this.props.openEditMetadata(this.props.bundleId, undefined, false); - } + const { openEditEntryMetadata, bundleId } = this.props; + openEditEntryMetadata(bundleId, undefined, false); + }; handleSwitchToResources = () => { - const { bundleId } = this.props; + const { openEntryResourceManager, bundleId } = this.props; const mode = this.getResourceMode(); - this.props.openResourceManager(bundleId, mode, false); - } + openEntryResourceManager(bundleId, mode, false); + }; handleSwitchToRevisions = () => { - const { bundleId } = this.props; - this.props.openResourceManager(bundleId, 'revisions', false); - } + const { openEntryResourceManager, bundleId } = this.props; + openEntryResourceManager(bundleId, 'revisions', false); + }; handleSwitchToReports = () => { - const { bundleId } = this.props; - this.props.openEntryReports(bundleId, 'reports'); - } + const { switchToEntryReports, bundleId } = this.props; + switchToEntryReports(bundleId, 'reports'); + }; render() { - const { - classes - } = this.props; + const { classes } = this.props; const items = this.getDrawerItems(); - const { theme, openDrawer } = this.props; + const { theme, openDrawer, hideEntryDrawer } = this.props; return ( { anchor="right" open={openDrawer} classes={{ - paper: classes.drawerPaper, + paper: classes.drawerPaper }} >
- - {theme.direction === 'rtl' ? : } + + {theme.direction === 'rtl' ? ( + + ) : ( + + )}
- - + + + + - - {items.map(this.renderListItem)} - - { /* + {items.map(this.renderListItem)} + {/* {['Make Revision', 'Export To', 'Copy As'].map((text, index) => ( diff --git a/app/helpers/bundle.helpers.js b/app/helpers/bundle.helpers.js new file mode 100644 index 0000000000..0d4584d23d --- /dev/null +++ b/app/helpers/bundle.helpers.js @@ -0,0 +1,34 @@ +export const bundleHelpers = { + getResourcePaths, + getResourcesDetails, + getAddedBundle, + getRawBundleResourcesDetails +}; +export default bundleHelpers; + +export function getStoredResourcePaths(getState, id) { + const bundle = getAddedBundle(getState, id); + return Object.keys(bundle.storedFiles); +} + +export function getResourcePaths(getState, id) { + return Object.keys(getResourcesDetails(getState, id)) || []; +} + +export function getResourcesDetails(getState, id) { + const bundle = getAddedBundle(getState, id); + return getRawBundleResourcesDetails(bundle.raw); +} + +export function getAddedBundle(getState, bundleId) { + const { bundles } = getState(); + const { addedByBundleIds = {} } = bundles; + const addedBundles = addedByBundleIds[bundleId]; + return addedBundles; +} + +// TODO: make a separate helper for raw bundles than for getState? +export function getRawBundleResourcesDetails(rawBundle) { + const { metadata } = rawBundle; + return metadata.manifest; +} diff --git a/app/services/bundle.service.js b/app/services/bundle.service.js index dbe11a1bd1..84575f1b93 100644 --- a/app/services/bundle.service.js +++ b/app/services/bundle.service.js @@ -2,7 +2,6 @@ import log from 'electron-log'; import traverse from 'traverse'; import fs from 'fs-extra'; import path from 'path'; -import rp from 'request-promise-native'; import got from 'got'; import FormData from 'form-data'; import uuidv1 from 'uuid/v1'; @@ -11,6 +10,7 @@ import { authHeader } from '../helpers'; import { servicesHelpers } from '../helpers/services'; import dblDotLocalConfigConstants from '../constants/dblDotLocal.constants'; import download from './download-with-fetch.flow'; +import { getRawBundleResourcesDetails } from '../helpers/bundle.helpers'; const { app } = require('electron').remote; @@ -25,12 +25,9 @@ export const bundleService = { apiBundleHasMetadata, convertApiBundleToNathanaelBundle, getInitialTaskAndStatus, - getManifestResourcePaths, - getManifestResourceDetails, deleteManifestResource, downloadResources, removeResources, - getResourcePaths, requestSaveResourceTo, saveMetadataToTempFolder, saveJobSpecToTempFolder, @@ -73,13 +70,11 @@ export default bundleService; const BUNDLE_API = 'bundle'; const BUNDLE_API_LIST = `${BUNDLE_API}/list`; const RESOURCE_API = 'resource'; -const RESOURCE_API_LIST = RESOURCE_API; const FORM_API = 'form'; const FORM_BUNDLE_API = `${FORM_API}/bundle`; const FORM_BUNDLE_API_DELETE = `${FORM_API}/delete`; const MANIFEST_API = 'manifest'; const DEBUG_API = 'debug'; -const MANIFEST_DETAILS = 'details'; const PUBLICATION_API = 'publication'; const SUBSYSTEM_API = 'subsystem'; @@ -207,11 +202,7 @@ function getResourceFileStoredCount(apiBundle) { async function convertApiBundleToNathanaelBundle(apiBundle, lazyLoads = {}) { const { mode, metadata, dbl, upload } = apiBundle; - const { - resourceCountManifest = null, - formsErrorStatus = {}, - manifestResources = [] - } = lazyLoads; + const { formsErrorStatus = {} } = lazyLoads; const { jobId: uploadJob } = upload || {}; const { parent } = dbl; const bundleId = apiBundle.local_id; @@ -226,15 +217,22 @@ async function convertApiBundleToNathanaelBundle(apiBundle, lazyLoads = {}) { status = 'COMPLETED'; // even if only some are stored } } + const sep = '/'; + const manifestResources = getRawBundleResourcesDetails(apiBundle); + const resourceCountManifest = (Object.values(manifestResources) || []).length; return { id: bundleId, - name: metadata.name, + name: metadata.identification.name, revision: dbl.currentRevision, dblId: dbl.id, medium: dbl.medium, - countryIso: metadata.countries || '', - languageIso: metadata.language, - rightsHolders: metadata.rightsHolders || '', + countryIso: Object.keys(metadata.countries).join(sep) || '', + languageIso: metadata.language.iso, + rightsHolders: + metadata.agencies + .filter(a => a.type === 'rightsHolder') + .map(a => a.abbr) + .join(sep) || '', license: dbl.license || 'owned', mode, task, @@ -302,24 +300,6 @@ function handlePostFormResponse(response) { return response.text(); } -function getManifestResourcePaths(bundleId) { - const requestOptions = { - method: 'GET', - headers: authHeader() - }; - const url = `${dblDotLocalConfigConstants.getHttpDblDotLocalBaseUrl()}/${MANIFEST_API}/${bundleId}`; - return fetch(url, requestOptions).then(handleResponse); -} - -function getManifestResourceDetails(bundleId) { - const requestOptions = { - method: 'GET', - headers: authHeader() - }; - const url = `${dblDotLocalConfigConstants.getHttpDblDotLocalBaseUrl()}/${MANIFEST_API}/${bundleId}/${MANIFEST_DETAILS}`; - return fetch(url, requestOptions).then(handleResponse); -} - function deleteManifestResource(bundleId, uri) { const requestOptions = { method: 'POST', @@ -415,18 +395,12 @@ function bundleAddTasks(bundleId, innerTasks) { return fetch(url, requestOptions).then(handlePostFormResponse); } -function getResourcePaths(bundleId) { - const requestOptions = { - method: 'GET', - headers: authHeader() - }; - const url = `${dblDotLocalConfigConstants.getHttpDblDotLocalBaseUrl()}/${BUNDLE_API}/${bundleId}/${RESOURCE_API_LIST}`; - return fetch(url, requestOptions).then(handleResponse); -} - async function saveMetadataToTempFolder(bundleId) { - const { tmpFolder, filePath: metadataFile, fileName: metadataXmlResource } - = getTempFolderForFile(bundleId, 'metadata.xml'); + const { + tmpFolder, + filePath: metadataFile, + fileName: metadataXmlResource + } = getTempFolderForFile(bundleId, 'metadata.xml'); await bundleService.requestSaveResourceTo( tmpFolder, bundleId, @@ -441,13 +415,18 @@ function getTempFolderForFile(bundleId, fileName) { const tmpFolder = path.join(temp, bundleId); const filePath = path.join(tmpFolder, fileName); return { - temp, tmpFolder, filePath, fileName + temp, + tmpFolder, + filePath, + fileName }; } async function saveJobSpecToTempFolder(bundleId) { - const { filePath: jobSpecPath } - = getTempFolderForFile(bundleId, 'job-spec.xml'); + const { filePath: jobSpecPath } = getTempFolderForFile( + bundleId, + 'job-spec.xml' + ); const url = `${dblDotLocalConfigConstants.getHttpDblDotLocalBaseUrl()}/${DEBUG_API}/${bundleId}/job-spec`; await download(url, jobSpecPath, () => {}, authHeader()); return jobSpecPath; @@ -499,7 +478,10 @@ function getFormFields(bundleId, formKey) { "response_valid": false } */ -async function waitUntilPostFormFields(postFormFieldArgs, doStopCreateMode = false) { +async function waitUntilPostFormFields( + postFormFieldArgs, + doStopCreateMode = false +) { const { bundleId } = postFormFieldArgs; await bundleService.waitStartCreateMode(bundleId); try { diff --git a/babel.config.js b/babel.config.js index 53fc093b5f..84e5c87f79 100644 --- a/babel.config.js +++ b/babel.config.js @@ -24,6 +24,7 @@ module.exports = api => { require('@babel/preset-env'), { targets: { electron: require('electron/package.json').version }, + corejs: '2', useBuiltIns: 'usage' } ], diff --git a/package.json b/package.json index 7ab2ecb4ad..ace1dca07c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "nathanael", "productName": "nathanael", - "version": "0.37.1", + "version": "0.37.2", "description": "Electron frontend to DBL dot Local", "scripts": { "build": "concurrently \"yarn build-main\" \"yarn build-renderer\"", @@ -289,7 +289,6 @@ "redux-debounced": "^0.5.0", "redux-thunk": "^2.3.0", "request": "2.34", - "request-promise-native": "^1.0.7", "reselect": "^3.0.1", "source-map-support": "^0.5.11", "split-string": "^5.0.4", diff --git a/yarn.lock b/yarn.lock index 85ec70330c..5deb8f4a98 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12278,7 +12278,7 @@ request-promise-core@1.1.2: dependencies: lodash "^4.17.11" -request-promise-native@^1.0.5, request-promise-native@^1.0.7: +request-promise-native@^1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.7.tgz#a49868a624bdea5069f1251d0a836e0d89aa2c59" integrity sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==