forked from extern/bruno
feat: collections are stored as objects in workspaces
This commit is contained in:
parent
d546709b26
commit
91981a48e4
@ -16,11 +16,13 @@ const SelectCollection = ({onClose, onSelect, title}) => {
|
|||||||
handleCancel={onClose}
|
handleCancel={onClose}
|
||||||
>
|
>
|
||||||
<ul className="mb-2" >
|
<ul className="mb-2" >
|
||||||
{collections && collections.length && collections.map((c) => (
|
{(collections && collections.length) ? collections.map((c) => (
|
||||||
<div className="collection" key={c.uid} onClick={() => onSelect(c.uid)}>
|
<div className="collection" key={c.uid} onClick={() => onSelect(c.uid)}>
|
||||||
<IconFiles size={18} strokeWidth={1.5}/> <span className="ml-2">{c.name}</span>
|
<IconFiles size={18} strokeWidth={1.5}/> <span className="ml-2">{c.name}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
)) : (
|
||||||
|
<div>No collections found</div>
|
||||||
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
</Modal>
|
</Modal>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
|
@ -4,6 +4,7 @@ import find from 'lodash/find';
|
|||||||
import filter from 'lodash/filter';
|
import filter from 'lodash/filter';
|
||||||
import Collection from './Collection';
|
import Collection from './Collection';
|
||||||
import CreateOrAddCollection from './CreateOrAddCollection';
|
import CreateOrAddCollection from './CreateOrAddCollection';
|
||||||
|
import { findCollectionInWorkspace } from 'utils/workspaces';
|
||||||
|
|
||||||
const Collections = ({searchText}) => {
|
const Collections = ({searchText}) => {
|
||||||
const { collections } = useSelector((state) => state.collections);
|
const { collections } = useSelector((state) => state.collections);
|
||||||
@ -14,8 +15,7 @@ const Collections = ({searchText}) => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { collectionUids } = activeWorkspace;
|
const collectionToDisplay = filter(collections, (c) => findCollectionInWorkspace(activeWorkspace, c.uid));
|
||||||
const collectionToDisplay = filter(collections, (c) => collectionUids.includes(c.uid));
|
|
||||||
|
|
||||||
if(!collectionToDisplay || !collectionToDisplay.length) {
|
if(!collectionToDisplay || !collectionToDisplay.length) {
|
||||||
return <CreateOrAddCollection />;
|
return <CreateOrAddCollection />;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import each from 'lodash/each';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import { uuid } from 'utils/common';
|
import { uuid } from 'utils/common';
|
||||||
import cloneDeep from 'lodash/cloneDeep';
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
|
@ -3,6 +3,7 @@ import filter from 'lodash/filter';
|
|||||||
import { uuid } from 'utils/common';
|
import { uuid } from 'utils/common';
|
||||||
import cloneDeep from 'lodash/cloneDeep';
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
import { workspaceSchema } from '@usebruno/schema';
|
import { workspaceSchema } from '@usebruno/schema';
|
||||||
|
import { findCollectionInWorkspace } from 'utils/workspaces';
|
||||||
import { getWorkspacesFromIdb, saveWorkspaceToIdb, deleteWorkspaceInIdb } from 'utils/idb/workspaces';
|
import { getWorkspacesFromIdb, saveWorkspaceToIdb, deleteWorkspaceInIdb } from 'utils/idb/workspaces';
|
||||||
import {
|
import {
|
||||||
loadWorkspaces,
|
loadWorkspaces,
|
||||||
@ -18,7 +19,7 @@ const seedWorkpace = () => {
|
|||||||
const workspace = {
|
const workspace = {
|
||||||
uid: uid,
|
uid: uid,
|
||||||
name: 'My workspace',
|
name: 'My workspace',
|
||||||
collectionUids: []
|
collections: []
|
||||||
};
|
};
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -52,7 +53,7 @@ export const addWorkspace = (workspaceName) => (dispatch) => {
|
|||||||
const newWorkspace = {
|
const newWorkspace = {
|
||||||
uid: uuid(),
|
uid: uuid(),
|
||||||
name: workspaceName,
|
name: workspaceName,
|
||||||
collectionUids: []
|
collections: []
|
||||||
};
|
};
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -131,12 +132,16 @@ export const addCollectionToWorkspace = (workspaceUid, collectionUid) => (dispat
|
|||||||
}
|
}
|
||||||
|
|
||||||
const workspaceCopy = cloneDeep(workspace);
|
const workspaceCopy = cloneDeep(workspace);
|
||||||
if(workspaceCopy.collectionUids && workspace.collectionUids.length) {
|
if(workspaceCopy.collections && workspace.collections.length) {
|
||||||
if(!workspaceCopy.collectionUids.includes(collectionUid)) {
|
if(!findCollectionInWorkspace(workspace, collectionUid)) {
|
||||||
workspaceCopy.collectionUids.push(collectionUid);
|
workspaceCopy.collections.push([{
|
||||||
|
uid: collectionUid
|
||||||
|
}]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
workspaceCopy.collectionUids = [collectionUid];
|
workspaceCopy.collections = [{
|
||||||
|
uid: collectionUid
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
workspaceSchema
|
workspaceSchema
|
||||||
@ -167,8 +172,8 @@ export const removeCollectionFromWorkspace = (workspaceUid, collectionUid) => (d
|
|||||||
}
|
}
|
||||||
|
|
||||||
const workspaceCopy = cloneDeep(workspace);
|
const workspaceCopy = cloneDeep(workspace);
|
||||||
if(workspaceCopy.collectionUids && workspace.collectionUids.length) {
|
if(workspaceCopy.collections && workspace.collections.length) {
|
||||||
workspaceCopy.collectionUids = filter(workspaceCopy.collectionUids, (uid) => uid !== collectionUid);
|
workspaceCopy.collections = filter(workspaceCopy.collections, (c) => c.uid !== collectionUid);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveWorkspaceToIdb(window.__idb, workspaceCopy)
|
saveWorkspaceToIdb(window.__idb, workspaceCopy)
|
||||||
@ -184,5 +189,5 @@ export const removeCollectionFromWorkspace = (workspaceUid, collectionUid) => (d
|
|||||||
// TODO
|
// TODO
|
||||||
// Workspaces can have collection uids that no longer exist
|
// Workspaces can have collection uids that no longer exist
|
||||||
// or the user may have the collections access revoked (in teams)
|
// or the user may have the collections access revoked (in teams)
|
||||||
// This action will have to be called at the beginning to purge any zombi collectionUids in the workspaces
|
// This action will have to be called at the beginning to purge any zombi collection references in the workspaces
|
||||||
export const removeZombieCollectionFromAllWorkspaces = (collectionUid) => (dispatch, getState) => {};
|
export const removeZombieCollectionFromAllWorkspaces = (workspaceUid) => (dispatch, getState) => {};
|
@ -1,6 +1,7 @@
|
|||||||
import { createSlice } from '@reduxjs/toolkit';
|
import { createSlice } from '@reduxjs/toolkit';
|
||||||
import find from 'lodash/find';
|
import find from 'lodash/find';
|
||||||
import filter from 'lodash/filter';
|
import filter from 'lodash/filter';
|
||||||
|
import { findCollectionInWorkspace } from 'utils/workspaces';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
workspaces: [],
|
workspaces: [],
|
||||||
@ -43,12 +44,16 @@ export const workspacesSlice = createSlice({
|
|||||||
const workspace = find(state.workspaces, (w) => w.uid === workspaceUid);
|
const workspace = find(state.workspaces, (w) => w.uid === workspaceUid);
|
||||||
|
|
||||||
if(workspace) {
|
if(workspace) {
|
||||||
if(workspace.collectionUids && workspace.collectionUids.length) {
|
if(workspace.collections && workspace.collections.length) {
|
||||||
if(!workspace.collectionUids.includes(collectionUid)) {
|
if(!findCollectionInWorkspace(workspace, collectionUid)) {
|
||||||
workspace.collectionUids.push(collectionUid);
|
workspace.collections.push([{
|
||||||
|
uid: collectionUid
|
||||||
|
}]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
workspace.collectionUids = [collectionUid];
|
workspace.collections = [{
|
||||||
|
uid: collectionUid
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -56,8 +61,8 @@ export const workspacesSlice = createSlice({
|
|||||||
const { workspaceUid, collectionUid } = action.payload;
|
const { workspaceUid, collectionUid } = action.payload;
|
||||||
const workspace = find(state.workspaces, (w) => w.uid === workspaceUid);
|
const workspace = find(state.workspaces, (w) => w.uid === workspaceUid);
|
||||||
|
|
||||||
if(workspace && workspace.collectionUids && workspace.collectionUids.length) {
|
if(workspace && workspace.collections && workspace.collections.length) {
|
||||||
workspace.collectionUids = filter(workspace.collectionUids, (uid) => uid !== collectionUid);
|
workspace.collections = filter(workspace.collections, (c) => c.uid !== collectionUid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
5
packages/bruno-app/src/utils/workspaces/index.js
Normal file
5
packages/bruno-app/src/utils/workspaces/index.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import find from 'lodash/find';
|
||||||
|
|
||||||
|
export const findCollectionInWorkspace = (workspace, collectionUid) => {
|
||||||
|
return find(workspace.collections, (c) => c.uid === collectionUid);
|
||||||
|
};
|
@ -1,13 +1,17 @@
|
|||||||
const Yup = require('yup');
|
const Yup = require('yup');
|
||||||
const { uidSchema } = require("../common");
|
const { uidSchema } = require("../common");
|
||||||
|
|
||||||
|
const collectionsSchema = Yup.object({
|
||||||
|
uid: uidSchema,
|
||||||
|
}).noUnknown(true).strict();
|
||||||
|
|
||||||
const workspaceSchema = Yup.object({
|
const workspaceSchema = Yup.object({
|
||||||
uid: uidSchema,
|
uid: uidSchema,
|
||||||
name: Yup.string()
|
name: Yup.string()
|
||||||
.min(1, 'name must be atleast 1 characters')
|
.min(1, 'name must be atleast 1 characters')
|
||||||
.max(50, 'name must be 50 characters or less')
|
.max(50, 'name must be 50 characters or less')
|
||||||
.required('name is required'),
|
.required('name is required'),
|
||||||
collectionUids: Yup.array().of(uidSchema)
|
collections: Yup.array().of(collectionsSchema)
|
||||||
}).noUnknown(true).strict();
|
}).noUnknown(true).strict();
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@ -83,4 +83,29 @@ describe('Workspace Schema Validation', () => {
|
|||||||
)
|
)
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('workspace schema must validate successfully with collections', async () => {
|
||||||
|
const workspace = {
|
||||||
|
uid: uuid(),
|
||||||
|
name: 'My workspace' ,
|
||||||
|
collections: [{uid: uuid()}]
|
||||||
|
};
|
||||||
|
|
||||||
|
const isValid = await workspaceSchema.validate(workspace);
|
||||||
|
expect(isValid).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('workspace schema throw an error when collections has an unknown property', async () => {
|
||||||
|
const workspace = {
|
||||||
|
uid: uuid(),
|
||||||
|
name: 'My workspace' ,
|
||||||
|
collections: [{uid: uuid(), foo: 'bar'}]
|
||||||
|
};
|
||||||
|
|
||||||
|
return Promise.all([
|
||||||
|
expect(workspaceSchema.validate(workspace)).rejects.toEqual(
|
||||||
|
validationErrorWithMessages('collections[0] field has unspecified keys: foo')
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user