@replyke/core
Version:
Replyke: Build interactive apps with social features like comments, votes, feeds, user lists, notifications, and more.
245 lines • 13.5 kB
JavaScript
;
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.selectCollectionEntities = exports.selectCurrentCollectionId = exports.selectCurrentProjectId = exports.selectCollectionsById = exports.selectSubCollectionsMap = exports.selectCollectionHistory = exports.selectCollectionsLoading = exports.selectSubCollections = exports.selectCurrentCollection = exports.handleError = exports.resetCollections = exports.insertCollectionEntityAt = exports.removeCollectionEntity = exports.prependCollectionEntity = exports.appendCollectionEntities = exports.setCollectionEntities = exports.handleCollectionDeletion = exports.removeCollectionFromSubCollections = exports.addNewCollectionAndNavigate = exports.updateCollectionInSubCollections = exports.updateCurrentCollection = exports.setSubCollections = exports.setCurrentCollection = exports.goToRoot = exports.goBack = exports.openCollection = exports.setLoading = exports.setProjectContext = exports.collectionsSlice = void 0;
const toolkit_1 = require("@reduxjs/toolkit");
// Initial state
const initialState = {
collectionsById: {},
subcollectionsMap: {},
currentCollectionId: null,
collectionHistory: [],
loading: false,
currentProjectId: undefined,
entitiesByCollectionId: {},
};
// Create the slice
exports.collectionsSlice = (0, toolkit_1.createSlice)({
name: "collections",
initialState,
reducers: {
// Set the current project context
setProjectContext: (state, action) => {
state.currentProjectId = action.payload;
},
// Set loading state
setLoading: (state, action) => {
state.loading = action.payload;
},
// Navigation actions
openCollection: (state, action) => {
const collection = action.payload;
// Store the collection if not already stored
if (!state.collectionsById[collection.id]) {
state.collectionsById[collection.id] = collection;
}
// Push current collection ID to history stack before opening new one
if (state.currentCollectionId) {
state.collectionHistory.push(state.currentCollectionId);
}
// Set new current collection ID
state.currentCollectionId = collection.id;
},
goBack: (state) => {
if (state.collectionHistory.length === 0)
return;
const previousCollectionId = state.collectionHistory.pop();
if (!previousCollectionId)
return;
state.currentCollectionId = previousCollectionId;
},
goToRoot: (state) => {
if (state.collectionHistory.length === 0)
return;
const rootCollectionId = state.collectionHistory[0];
state.collectionHistory = [];
state.currentCollectionId = rootCollectionId;
},
// Set current collection (for initial root collection fetch)
setCurrentCollection: (state, action) => {
const collection = action.payload;
if (collection) {
state.collectionsById[collection.id] = collection;
state.currentCollectionId = collection.id;
}
else {
state.currentCollectionId = null;
}
},
// Set sub-collections and update mapping
setSubCollections: (state, action) => {
const { collections, parentCollectionId } = action.payload;
// Store all collections in collectionsById
collections.forEach(collection => {
state.collectionsById[collection.id] = collection;
});
// Update parent-child mapping
state.subcollectionsMap[parentCollectionId] = collections.map(collection => collection.id);
},
// Update current collection (for entity add/remove operations)
updateCurrentCollection: (state, action) => {
const updatedCollection = action.payload;
// Update in collectionsById (single source of truth)
state.collectionsById[updatedCollection.id] = updatedCollection;
},
// Update a collection (now just updates in collectionsById)
updateCollectionInSubCollections: (state, action) => {
const updatedCollection = action.payload;
// Update in collectionsById (single source of truth)
state.collectionsById[updatedCollection.id] = updatedCollection;
},
// Add new collection to sub-collections and navigate to it
addNewCollectionAndNavigate: (state, action) => {
const newCollection = action.payload;
if (!state.currentCollectionId)
return;
// Store the new collection
state.collectionsById[newCollection.id] = newCollection;
// Push current collection ID to history
state.collectionHistory.push(state.currentCollectionId);
// Set new collection as current
state.currentCollectionId = newCollection.id;
// Update parent-child mapping
if (newCollection.parentId) {
if (!state.subcollectionsMap[newCollection.parentId]) {
state.subcollectionsMap[newCollection.parentId] = [];
}
if (!state.subcollectionsMap[newCollection.parentId].includes(newCollection.id)) {
state.subcollectionsMap[newCollection.parentId].push(newCollection.id);
}
}
},
// Remove collection from sub-collections and storage
removeCollectionFromSubCollections: (state, action) => {
const collectionId = action.payload;
// Remove from collectionsById
delete state.collectionsById[collectionId];
// Remove from all parent-child mappings
Object.keys(state.subcollectionsMap).forEach((parentId) => {
state.subcollectionsMap[parentId] = state.subcollectionsMap[parentId].filter((id) => id !== collectionId);
});
// Remove its own sub-collections mapping if it exists
delete state.subcollectionsMap[collectionId];
},
// Handle collection deletion
handleCollectionDeletion: (state, action) => {
const { collectionId, parentId } = action.payload;
// Remove from parent-child mapping
if (parentId && state.subcollectionsMap[parentId]) {
state.subcollectionsMap[parentId] = state.subcollectionsMap[parentId].filter((id) => id !== collectionId);
}
// Remove from collectionsById
delete state.collectionsById[collectionId];
// Remove its own sub-collections mapping
delete state.subcollectionsMap[collectionId];
// Remove its entity list
delete state.entitiesByCollectionId[collectionId];
// If deleted collection is current collection, go back
if (state.currentCollectionId === collectionId) {
if (state.collectionHistory.length === 0) {
state.currentCollectionId = null;
return;
}
const previousCollectionId = state.collectionHistory.pop();
if (!previousCollectionId) {
state.currentCollectionId = null;
return;
}
state.currentCollectionId = previousCollectionId;
}
},
// Entity list management (shared state for optimistic add/remove)
setCollectionEntities: (state, action) => {
const { collectionId, entities } = action.payload;
state.entitiesByCollectionId[collectionId] = entities;
},
appendCollectionEntities: (state, action) => {
const { collectionId, entities } = action.payload;
if (!state.entitiesByCollectionId[collectionId]) {
state.entitiesByCollectionId[collectionId] = [];
}
state.entitiesByCollectionId[collectionId].push(...entities);
},
prependCollectionEntity: (state, action) => {
const { collectionId, entity } = action.payload;
if (!state.entitiesByCollectionId[collectionId]) {
state.entitiesByCollectionId[collectionId] = [];
}
state.entitiesByCollectionId[collectionId].unshift(entity);
},
removeCollectionEntity: (state, action) => {
const { collectionId, entityId } = action.payload;
if (state.entitiesByCollectionId[collectionId]) {
state.entitiesByCollectionId[collectionId] =
state.entitiesByCollectionId[collectionId].filter((e) => e.id !== entityId);
}
},
insertCollectionEntityAt: (state, action) => {
const { collectionId, entity, index } = action.payload;
if (!state.entitiesByCollectionId[collectionId]) {
state.entitiesByCollectionId[collectionId] = [];
}
const clamped = Math.min(index, state.entitiesByCollectionId[collectionId].length);
state.entitiesByCollectionId[collectionId].splice(clamped, 0, entity);
},
// Reset all collections data
resetCollections: (state) => {
state.collectionsById = {};
state.subcollectionsMap = {};
state.currentCollectionId = null;
state.collectionHistory = [];
state.loading = false;
state.entitiesByCollectionId = {};
},
// Handle errors by stopping loading
handleError: (state) => {
state.loading = false;
},
},
});
// Export actions
_a = exports.collectionsSlice.actions, exports.setProjectContext = _a.setProjectContext, exports.setLoading = _a.setLoading, exports.openCollection = _a.openCollection, exports.goBack = _a.goBack, exports.goToRoot = _a.goToRoot, exports.setCurrentCollection = _a.setCurrentCollection, exports.setSubCollections = _a.setSubCollections, exports.updateCurrentCollection = _a.updateCurrentCollection, exports.updateCollectionInSubCollections = _a.updateCollectionInSubCollections, exports.addNewCollectionAndNavigate = _a.addNewCollectionAndNavigate, exports.removeCollectionFromSubCollections = _a.removeCollectionFromSubCollections, exports.handleCollectionDeletion = _a.handleCollectionDeletion, exports.setCollectionEntities = _a.setCollectionEntities, exports.appendCollectionEntities = _a.appendCollectionEntities, exports.prependCollectionEntity = _a.prependCollectionEntity, exports.removeCollectionEntity = _a.removeCollectionEntity, exports.insertCollectionEntityAt = _a.insertCollectionEntityAt, exports.resetCollections = _a.resetCollections, exports.handleError = _a.handleError;
// Export reducer
exports.default = exports.collectionsSlice.reducer;
// Selectors - use namespaced state for dual-mode support
const selectCurrentCollection = (state) => {
const { currentCollectionId, collectionsById } = state.replyke.collections;
return currentCollectionId ? collectionsById[currentCollectionId] || null : null;
};
exports.selectCurrentCollection = selectCurrentCollection;
exports.selectSubCollections = (0, toolkit_1.createSelector)([(state) => state.replyke.collections.currentCollectionId,
(state) => state.replyke.collections.subcollectionsMap,
(state) => state.replyke.collections.collectionsById], (currentCollectionId, subcollectionsMap, collectionsById) => {
if (!currentCollectionId || !subcollectionsMap[currentCollectionId]) {
return [];
}
return subcollectionsMap[currentCollectionId]
.map(collectionId => collectionsById[collectionId])
.filter(Boolean); // Remove any undefined entries
});
const selectCollectionsLoading = (state) => state.replyke.collections.loading;
exports.selectCollectionsLoading = selectCollectionsLoading;
exports.selectCollectionHistory = (0, toolkit_1.createSelector)([(state) => state.replyke.collections.collectionHistory,
(state) => state.replyke.collections.collectionsById], (collectionHistory, collectionsById) => {
return collectionHistory
.map(collectionId => collectionsById[collectionId])
.filter(Boolean); // Remove any undefined entries
});
// Selector for the sub-collections mapping
const selectSubCollectionsMap = (state) => state.replyke.collections.subcollectionsMap;
exports.selectSubCollectionsMap = selectSubCollectionsMap;
// Selector for all collections
const selectCollectionsById = (state) => state.replyke.collections.collectionsById;
exports.selectCollectionsById = selectCollectionsById;
const selectCurrentProjectId = (state) => state.replyke.collections.currentProjectId;
exports.selectCurrentProjectId = selectCurrentProjectId;
// Selector for current collection ID
const selectCurrentCollectionId = (state) => state.replyke.collections.currentCollectionId;
exports.selectCurrentCollectionId = selectCurrentCollectionId;
const EMPTY_ENTITIES = [];
// Selector for entities in a specific collection
const selectCollectionEntities = (collectionId) => (state) => collectionId
? (state.replyke.collections.entitiesByCollectionId[collectionId] ?? EMPTY_ENTITIES)
: EMPTY_ENTITIES;
exports.selectCollectionEntities = selectCollectionEntities;
//# sourceMappingURL=collectionsSlice.js.map