Skip to content

Commit

Permalink
Add support for moving collections to/from trash
Browse files Browse the repository at this point in the history
  • Loading branch information
tnajdek committed Sep 12, 2024
1 parent 2ae0a6f commit c1d41c6
Show file tree
Hide file tree
Showing 15 changed files with 315 additions and 110 deletions.
176 changes: 168 additions & 8 deletions src/js/actions/collections.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,19 @@ import {
REQUEST_UPDATE_COLLECTION,
BEGIN_FETCH_COLLECTIONS_SINCE,
COMPLETE_FETCH_COLLECTIONS_SINCE,
PRE_UPDATE_COLLECTIONS_TRASH,
REQUEST_UPDATE_COLLECTIONS_TRASH,
RECEIVE_UPDATE_COLLECTIONS_TRASH,
ERROR_UPDATE_COLLECTIONS_TRASH,
PRE_DELETE_COLLECTIONS,
REQUEST_DELETE_COLLECTIONS,
RECEIVE_DELETE_COLLECTIONS,
ERROR_DELETE_COLLECTIONS,
} from '../constants/actions';

import { requestTracker, requestWithBackoff } from '.';
import { cede, get } from '../utils';
import { chunkedAction } from '../common/actions';

const rescheduleBadRequests = (badRequestsArray, allRequestsArray, dispatch, libraryKey, args) => {
let hasScheduledNewRequest = false;
Expand Down Expand Up @@ -352,13 +361,164 @@ const deleteCollection = (collection, libraryKey) => {
};
}

const deleteCollections = (collectionKeys, libraryKey) => {
return async dispatch => {
const id = requestTracker.id++;

dispatch({
type: PRE_DELETE_COLLECTIONS,
collectionKeys,
libraryKey,
id
});

const promise = new Promise((resolve, reject) => {
dispatch(
queueDeleteCollections(collectionKeys, libraryKey, id, resolve, reject)
);
});
return promise;
};
}

const chunkedDeleteCollections = (...args) => chunkedAction(deleteCollections, ...args);

const queueDeleteCollections = (collectionKeys, libraryKey, id, resolve, reject) => {
return {
queue: libraryKey,
callback: async (next, dispatch, getState) => {
const config = getState().config;

dispatch({
type: REQUEST_DELETE_COLLECTIONS,
libraryKey,
collectionKeys,
id
});

try {
let response = await api(config.apiKey, config.apiConfig)
.library(libraryKey)
.collections()
.delete(collectionKeys);

dispatch({
type: RECEIVE_DELETE_COLLECTIONS,
libraryKey,
collectionKeys,
response,
id
});
resolve(response);
} catch(error) {
dispatch({
type: ERROR_DELETE_COLLECTIONS,
error,
libraryKey,
collectionKeys,
id
});
reject(error);
} finally {
next();
}
}
};
}

const updateCollectionsTrash = (collectionKeys, libraryKey, deleted) => {
return async dispatch => {
const id = requestTracker.id++;

if (deleted !== 0 && deleted !== 1) {
throw new Error('deleted must be 0 or 1');
}

dispatch({
type: PRE_UPDATE_COLLECTIONS_TRASH,
collectionKeys,
libraryKey,
deleted,
id
});

dispatch(
queueUpdateCollectionsTrash(collectionKeys, libraryKey, deleted, id)
);
};
}

const chunkedUpdateCollectionsTrash = (...args) => chunkedAction(updateCollectionsTrash, ...args);

const queueUpdateCollectionsTrash = (collectionKeys, libraryKey, deleted, id) => {
return {
queue: libraryKey,
callback: async (next, dispatch, getState) => {
const state = getState();
const config = state.config;
const version = state.libraries[libraryKey].sync.version;

dispatch({
type: REQUEST_UPDATE_COLLECTIONS_TRASH,
libraryKey,
collectionKeys,
deleted,
id
});

try {
let response = await api(config.apiKey, config.apiConfig)
.library(libraryKey)
.version(version)
.collections()
.post(collectionKeys.map(key => ({ key, deleted })));

const updatedCollectionsKeys = [];
const collections = [];

collectionKeys.forEach((_, index) => {
const updatedCollection = response.getEntityByIndex(index);
collections.push(updatedCollection);
updatedCollectionsKeys.push(updatedCollection.key);
});

dispatch({
type: RECEIVE_UPDATE_COLLECTIONS_TRASH,
libraryKey,
collections,
collectionKeys: updatedCollectionsKeys,
deleted,
response,
id
});
} catch(error) {
dispatch({
type: ERROR_UPDATE_COLLECTIONS_TRASH,
error,
libraryKey,
collectionKeys,
deleted,
id
});
throw error;
} finally {
next();
}
}
}
}

export {
createCollection,
createCollections,
deleteCollection,
fetchAllCollections,
fetchAllCollectionsSince,
fetchCollections,
queueUpdateCollection,
updateCollection,
chunkedUpdateCollectionsTrash,
createCollection,
createCollections,
deleteCollection,
deleteCollections,
fetchAllCollections,
fetchAllCollectionsSince,
fetchCollections,
queueUpdateCollection,
updateCollection,
updateCollectionsTrash,
chunkedDeleteCollections
};
49 changes: 31 additions & 18 deletions src/js/actions/items-current.js → src/js/actions/current.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { omit } from 'web-common/utils';

import { getApiForItems } from '../common/actions';
import { getApiForItems, splitItemAndCollectionKeys } from '../common/actions';
import { exportItems, chunkedToggleTagsOnItems, chunkedAddToCollection, chunkedCopyToLibrary,
chunkedTrashOrDelete, chunkedDeleteItems, chunkedMoveToTrash, chunkedRecoverFromTrash,
chunkedRemoveFromCollection, createItem, createItemOfType, toggleModal } from '.';
chunkedDeleteItems, chunkedMoveItemsToTrash, chunkedRecoverItemsFromTrash,
chunkedRemoveFromCollection, chunkedUpdateCollectionsTrash, chunkedDeleteCollections, createItem, createItemOfType, toggleModal } from '.';
import columnProperties from '../constants/column-properties';
import { BIBLIOGRAPHY, COLLECTION_SELECT, EXPORT, NEW_FILE, NEW_ITEM } from '../constants/modals';
import { TOGGLE_ADD, TOGGLE_REMOVE } from '../common/tags';
Expand Down Expand Up @@ -90,35 +90,48 @@ const currentCiteModal = () => {
}
}

const currentTrashItems = () => {
const currentMoveToTrash = () => {
return async (dispatch, getState) => {
const state = getState();
const { itemKeys } = state.current;
return await dispatch(chunkedMoveToTrash(itemKeys));
const { itemKeys: keys, libraryKey } = state.current;
const { itemKeys, collectionKeys } = splitItemAndCollectionKeys(keys, libraryKey, state);
const itemsPromise = dispatch(chunkedMoveItemsToTrash(itemKeys));
const collectionsPromise = dispatch(chunkedUpdateCollectionsTrash(collectionKeys, libraryKey, 1));
return await Promise.all([itemsPromise, collectionsPromise]);
}
}

const currentRecoverTrashItems = () => {
const currentRecoverFromTrash = () => {
return async (dispatch, getState) => {
const state = getState();
const { itemKeys } = state.current;
return await dispatch(chunkedRecoverFromTrash(itemKeys));
const { itemKeys: keys, libraryKey } = state.current;
const { itemKeys, collectionKeys } = splitItemAndCollectionKeys(keys, libraryKey, state);
const itemsPromise = dispatch(chunkedRecoverItemsFromTrash(itemKeys));
const collectionsPromise = dispatch(chunkedUpdateCollectionsTrash(collectionKeys, libraryKey, 0));
return await Promise.all([itemsPromise, collectionsPromise]);
}
}

const currentTrashOrDelete = () => {
const currentDeletePermanently = () => {
return async (dispatch, getState) => {
const state = getState();
const { itemKeys } = state.current;
return await dispatch(chunkedTrashOrDelete(itemKeys));
const { itemKeys: keys, libraryKey } = state.current;
const { itemKeys, collectionKeys } = splitItemAndCollectionKeys(keys, libraryKey, state);
const itemsPromise = await dispatch(chunkedDeleteItems(itemKeys));
const collectionsPromise = await dispatch(chunkedDeleteCollections(collectionKeys, libraryKey));
return await Promise.all([itemsPromise, collectionsPromise]);
}
}

const currentDeleteItems = () => {
const currentTrashOrDelete = () => {
return async (dispatch, getState) => {
const state = getState();
const { itemKeys } = state.current;
return await dispatch(chunkedDeleteItems(itemKeys));
const { itemsSource } = state.current;
if (itemsSource === 'trash') {
return await dispatch(currentDeletePermanently());
} else {
return await dispatch(currentMoveToTrash());
}
}
}

Expand Down Expand Up @@ -254,17 +267,17 @@ export {
currentCiteModal,
currentCopyToLibrary,
currentCreateItemOfType,
currentDeleteItems,
currentDeletePermanently,
currentDuplicateItem,
currentExportItems,
currentExportItemsModal,
currentGoToSubscribeUrl,
currentNewFileModal,
currentNewItemModal,
currentRecoverTrashItems,
currentRecoverFromTrash,
currentRemoveColoredTags,
currentRemoveItemFromCollection,
currentToggleTagByIndex,
currentTrashItems,
currentMoveToTrash,
currentTrashOrDelete,
}
2 changes: 1 addition & 1 deletion src/js/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export * from "./items-export";
export * from "./items-other";
export * from "./items-read";
export * from "./items-write";
export * from './items-current';
export * from './current';
export * from "./library";
export * from "./meta";
export * from "./navigate";
Expand Down
Loading

0 comments on commit c1d41c6

Please sign in to comment.