{"version":3,"sources":["webpack:///./app/react/packages/folders/constants/index.js","webpack:///./app/react/packages/folders/context/actionTypes.js","webpack:///./app/react/packages/folders/context/actions.js","webpack:///./app/react/packages/folders/context/helpers/adjustFolder.js","webpack:///./app/react/packages/folders/context/helpers/withoutFolderId.js","webpack:///./app/react/packages/folders/context/helpers/withoutFolderItem.js","webpack:///./app/react/packages/folders/context/helpers/publishedFolders.js","webpack:///./app/react/packages/folders/context/helpers/sharedFolders.js","webpack:///./app/react/packages/folders/context/reducer.js","webpack:///./app/react/packages/folders/context/helpers/addNewFolder.js","webpack:///./app/react/packages/folders/context/helpers/replaceChangedFolders.js","webpack:///./app/react/packages/folders/services/endpoints.js","webpack:///./app/react/packages/folders/services/createFolder.js","webpack:///./app/react/packages/folders/services/index.js","webpack:///./app/react/packages/folders/services/copyFolder.js","webpack:///./app/react/packages/folders/services/deleteFolder.js","webpack:///./app/react/packages/folders/services/deleteItem.js","webpack:///./app/react/packages/folders/services/getFolderContent.js","webpack:///./app/react/packages/folders/services/getFolders.js","webpack:///./app/react/packages/folders/services/publishFolder.js","webpack:///./app/react/packages/folders/services/putItem.js","webpack:///./app/react/packages/folders/services/sendFolderNotification.js","webpack:///./app/react/packages/folders/services/shareFolder.js","webpack:///./app/react/packages/folders/services/unpublishFolder.js","webpack:///./app/react/packages/folders/services/unshareFolder.js","webpack:///./app/react/packages/folders/services/updateFolder.js","webpack:///./app/react/packages/folders/services/updateFolderPosition.js","webpack:///./app/react/packages/folders/services/updateItemPosition.js","webpack:///./app/react/packages/folders/context/context.js","webpack:///./app/react/packages/folders/components/EmptyState.js","webpack:///./app/react/packages/folders/utils/sort.js","webpack:///./app/react/packages/folders/components/MoveItemModal.js"],"names":["sortTypes","ascending","descending","manual","author","date","itemTypes","course","flashcardCategory","flashcardSet","folder","lesson","post","video","addPublishedFolder","type","actionTypes","payload","adjustFolderShares","createFolder","deleteFolder","folderId","deleteItem","itemId","removeFolderShares","removePublishedFolder","setCurrentFolderId","setFolders","folders","setNewPublished","bool","setNewShared","sortAscending","sortDescending","sortManual","sortSharedAscending","sortSharedAuthor","sortSharedDate","sortSharedDescending","updateChangedFolders","changedFolders","updateFolder","id","name","description","index","Error","withoutFolderId","withoutFolderItem","folderIndex","folderItems","itemIndex","itemToRemove","withFolderPublished","eslPublishedAt","myFolders","withFolderUnpublished","publishedFolders","existingFolderIndex","sharedSchools","sharedUsers","foldersReducer","state","action","currentFolderId","repositionedFolders","map","f","position","adjustFolder","mergedFolders","changedFolder","indexFromMerged","hasNewPublished","hasNewShared","sort","sharedSort","foldersEndpoint","folderItemsEndpoint","copyFolder","xhr","url","method","item","data","folder_items_attributes","fileable_id","fileable","fileable_type","getFolderContent","getFolders","publishFolder","publishedAt","esl_published_at","putItem","fileableId","fileableType","inFolders","folder_item","sendFolderNotification","shareFolder","schools","users","unpublishFolder","unshareFolder","updateFolderPosition","updateItemPosition","FoldersState","createContext","FoldersDispatch","useFoldersContext","useContext","dispatch","undefined","FoldersProvider","children","getInitialState","initialState","sharedFolders","school","isPublisher","useReducer","foldersState","setFoldersState","Provider","value","ModalFoldersProvider","AsyncModalFoldersProvider","fallback","initialFolders","userLoggedIn","useUserAccess","useEffect","services","fetchedFolders","actions","fetchFolders","displayName","propTypes","PropTypes","node","isRequired","EmptyState","message","py","px","textAlign","bg","src","FolderOpen","alt","role","mb","mx","width","height","as","defaultProps","string","ascByFileableName","descByFileableName","ascByPosition","ascByFileablePosition","ascByAuthor","descByDate","MoveItemModal","isOpen","onClose","onMoveItem","dispatchFolders","sortedFolders","folderSorts","initialSelection","reduce","fs","useState","selection","setSelection","toggleFolderSelection","newFolderIds","setNewFolderIds","currentFolders","filter","includes","newFolders","newFolderRef","useRef","namingNewFolder","setNamingNewFolder","isNameError","setIsNameError","handleNewFolder","newFolder","current","focus","handleFolderRename","updatedFolder","movePending","setMovePending","handleMove","Object","keys","Number","length","shouldNotClose","x","Boolean","removeDisposedFolders","ids","tempFolder","find","forEach","cancelNewFolderBeforeClose","useDidMountEffect","Root","open","onOpenChange","Portal","Overlay","StyledContent","onPointerDownOutside","e","preventDefault","StyledTitle","fontSize","display","alignItems","p","my","borderRadius","icon","weight","color","pr","pt","maxHeight","overflowY","border","borderColor","newId","flexShrink","adaptive","checked","onChange","ml","defaultValue","placeholder","ref","autoComplete","onFocus","target","select","onKeyDown","keyCode","onBlur","trunclipse","pl","mt","justifyContent","secondary","onClick","disabled","mr","shape","number","func"],"mappings":"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","file":"package-folders.47de66ed7e06c2798daf.chunk.js","sourcesContent":["export const sortTypes = {\n ascending: 'ascending',\n descending: 'descending',\n manual: 'manual',\n author: 'author',\n date: 'date',\n}\n\nexport const itemTypes = {\n course: 'Course',\n flashcardCategory: 'FlashcardCategory',\n flashcardSet: 'FlashcardSet',\n folder: 'Folder',\n lesson: 'Lesson',\n post: 'Post',\n video: 'Video',\n}\n","export default {\n adjustFolderShares: 'adjust folder shares',\n addPublishedFolder: 'add published folder',\n createFolder: 'create folder',\n deleteFolder: 'delete folder',\n deleteFolderItem: 'delete folder item',\n removeFolderShares: 'remove folder shares',\n removePublishedFolder: 'remove published folder',\n setCurrentFolderId: 'set current folder ID',\n setFolders: 'set folders',\n setNewPublished: 'set new published',\n setNewShared: 'set new shared',\n sortAscending: 'sort ascending',\n sortDescending: 'sort descending',\n sortManual: 'sort manual',\n sortSharedAscending: 'sort shared ascending',\n sortSharedAuthor: 'sort shared author',\n sortSharedDate: 'sort shared date',\n sortSharedDescending: 'sort shared descending',\n updateChangedFolders: 'update changed folders',\n updateFolder: 'update folder',\n}\n","import { sortTypes } from '../constants'\n\nimport actionTypes from './actionTypes'\n\n// For setting initial folder state\n// and for reordering root level folders\nconst setFolders = folders => ({\n type: actionTypes.setFolders,\n payload: folders,\n})\n\nconst setCurrentFolderId = folderId => ({\n type: actionTypes.setCurrentFolderId,\n payload: folderId,\n})\n\n// FOLDER actionTypes\nconst createFolder = folder => ({\n type: actionTypes.createFolder,\n payload: folder,\n})\n\nconst updateFolder = ({ id, name, description }) => ({\n type: actionTypes.updateFolder,\n payload: {\n id,\n name,\n description,\n },\n})\n\nconst addPublishedFolder = folder => ({\n type: actionTypes.addPublishedFolder,\n payload: folder,\n})\n\nconst removePublishedFolder = folderId => ({\n type: actionTypes.removePublishedFolder,\n payload: folderId,\n})\n\nconst adjustFolderShares = folder => ({\n type: actionTypes.adjustFolderShares,\n payload: folder,\n})\n\nconst removeFolderShares = folderId => ({\n type: actionTypes.removeFolderShares,\n payload: folderId,\n})\n\nconst deleteFolder = folderId => ({\n type: actionTypes.deleteFolder,\n payload: folderId,\n})\n\n// FOLDER ITEM actionTypes\n\n// When moving folder items, the endpoint responds with an array\n// of folders which changed as a result of the move\nconst updateChangedFolders = changedFolders => ({\n type: actionTypes.updateChangedFolders,\n payload: changedFolders,\n})\n\nconst deleteItem = ({ folderId, itemId }) => ({\n type: actionTypes.deleteFolderItem,\n payload: {\n folderId,\n itemId,\n },\n})\n\n// UI\nconst setNewPublished = bool => ({\n type: actionTypes.setNewPublished,\n payload: bool,\n})\n\nconst setNewShared = bool => ({\n type: actionTypes.setNewShared,\n payload: bool,\n})\n\nconst sortAscending = () => ({\n type: actionTypes.sortAscending,\n payload: sortTypes.ascending,\n})\n\nconst sortDescending = () => ({\n type: actionTypes.sortDescending,\n payload: sortTypes.descending,\n})\n\nconst sortManual = () => ({\n type: actionTypes.sortManual,\n payload: sortTypes.manual,\n})\n\nconst sortSharedAscending = () => ({\n type: actionTypes.sortSharedAscending,\n payload: sortTypes.ascending,\n})\n\nconst sortSharedAuthor = () => ({\n type: actionTypes.sortSharedAuthor,\n payload: sortTypes.author,\n})\n\nconst sortSharedDate = () => ({\n type: actionTypes.sortSharedDate,\n payload: sortTypes.date,\n})\n\nconst sortSharedDescending = () => ({\n type: actionTypes.sortSharedDescending,\n payload: sortTypes.descending,\n})\n\nexport default {\n addPublishedFolder,\n adjustFolderShares,\n createFolder,\n deleteFolder,\n deleteItem,\n removeFolderShares,\n removePublishedFolder,\n setCurrentFolderId,\n setFolders,\n setNewPublished,\n setNewShared,\n sortAscending,\n sortDescending,\n sortManual,\n sortSharedAscending,\n sortSharedAuthor,\n sortSharedDate,\n sortSharedDescending,\n updateChangedFolders,\n updateFolder,\n}\n","import R from 'ramda'\n\n/**\n * Update a folder's name and/or description\n * @param {Object} folder - Information about the folder to be updated\n * @param {number} folder.id - The ID of the folder to be updated\n * @param {string} folder.name - The updated name to apply\n * @param {string} folder.description - The updated description to apply\n * @param {Array} folders - The array of folders from the current state\n */\nexport default function({ id, name, description }, folders) {\n const index = R.findIndex(R.propEq('id', id), folders)\n\n // findIndex returns -1 if index not found\n if (index < 0) throw new Error(`updateFolder: id ${id} not found in array`)\n\n // Folder at `index` passed as second arg to R.mergeLeft\n return R.adjust(index, R.mergeLeft({ name, description }), folders)\n}\n","import R from 'ramda'\n\n/**\n * Remove a folder of `id` from a list of folders\n * @param {number} id - The id of the folder to delete\n * @param {Array} folders - The array of folders from the current state\n */\nexport default function withoutFolderId(id, folders) {\n const folder = R.find(R.propEq('id', id), folders)\n\n if (!folder) throw new Error(`Folder with id ${id} not found in folders`)\n\n return R.without([folder], folders)\n}\n","import R from 'ramda'\n\n/**\n * Remove a folder item of `itemId` from a folder of `folderId` from a list of folders\n * @param {Object} item - Information about the item to be removed\n * @param {number} item.folderId - The ID of the folder the item should be removed from\n * @param {number} item.itemId - The ID of the item to be removed\n * @param {Array} folders - The array of folders from the current state\n */\nexport default function withoutFolderItem({ folderId, itemId }, folders) {\n const folderIndex = R.findIndex(R.propEq('id', folderId), folders)\n if (folderIndex < 0)\n throw new Error(`deleteFolderItem: id ${folderId} not found in array`)\n\n const { folderItems } = folders[folderIndex]\n\n const itemIndex = R.findIndex(R.propEq('id', itemId), folderItems)\n if (itemIndex < 0)\n throw new Error(\n `deleteFolderItem: id ${itemId} not found in [${folderId}].folderItems`\n )\n\n const itemToRemove = R.nth(itemIndex, folderItems)\n\n return R.adjust(\n folderIndex,\n R.mergeLeft({ folderItems: R.without([itemToRemove], folderItems) }),\n folders\n )\n}\n","import R from 'ramda'\n\n/**\n * Mark a folder in myFolders as published\n * @param {Object} config\n * @param {number} config.folderId - the ID of the folder to be updated\n * @param {string} config.eslPublishedAt - the datestring from the folder's eslPublishedAt field\n * @param {Object[]} config.myFolders - the current myFolders array from the application state\n */\nexport function withFolderPublished({ folderId, eslPublishedAt, myFolders }) {\n const index = R.findIndex(R.propEq('id', folderId), myFolders)\n\n if (index < 0)\n throw new Error(\n `withPublishedFolder: Folder with id ${folderId} not found in myFolders`\n )\n\n return R.adjust(index, R.mergeLeft({ eslPublishedAt }), myFolders)\n}\n\n/**\n * Mark a folder in myFolders as not published\n * @param {Object} config\n * @param {number} config.folderId - the ID of the folder to be updated\n * @param {Object[]} config.myFolders - the current myFolders array from the application state\n */\nexport function withFolderUnpublished({ folderId, myFolders }) {\n const index = R.findIndex(R.propEq('id', folderId), myFolders)\n\n if (index < 0)\n throw new Error(\n `withPublishedFolder: Folder with id ${folderId} not found in myFolders`\n )\n\n return R.adjust(index, R.mergeLeft({ eslPublishedAt: null }), myFolders)\n}\n\n/**\n * Add a folder to the publishedFolders array\n * @param {Object} config\n * @param {Object} config.folder - the folder to add\n * @param {Object[]} config.publishedFolders - the current publishedFolders array from the application state\n */\nexport function addPublishedFolder({ folder, publishedFolders }) {\n return R.append(folder, publishedFolders)\n}\n\n/**\n * Remove a folder from the publishedFolders array\n * @param {Object} config\n * @param {number} config.folderId - the ID of the folder to be removed\n * @param {Object[]} config.publishedFolders - the current publishedFolders array from the application state\n */\nexport function removePublishedFolder({ folderId, publishedFolders }) {\n const folder = R.find(R.propEq('id', folderId), publishedFolders)\n\n if (!folder)\n throw new Error(\n `removePublishedFolder: Folder with id ${folderId} not found in publishedFolders`\n )\n\n return R.without([folder], publishedFolders)\n}\n","import R from 'ramda'\n\n// Update a folder's sharedSchools and/or sharedUsers arrays\nexport function adjustFolderShares({ folder, myFolders }) {\n const existingFolderIndex = R.findIndex(R.propEq('id', folder.id), myFolders)\n\n if (existingFolderIndex < 0) {\n throw new Error(\n `updateSharedFolder: Folder with id ${folder.id} not found in myFolders`\n )\n }\n\n const { sharedSchools, sharedUsers } = folder\n\n return R.adjust(\n existingFolderIndex,\n R.mergeLeft({ sharedSchools, sharedUsers }),\n myFolders\n )\n}\n\n// Remove any school and/or user IDs from a folder's sharedSchools and sharedUsers arrays\nexport function removeFolderShares({ folderId, myFolders }) {\n const existingFolderIndex = R.findIndex(R.propEq('id', folderId), myFolders)\n\n if (existingFolderIndex < 0) {\n throw new Error(\n `removeFolderShares: Folder with id ${folderId} not found in myFolders`\n )\n }\n\n return R.adjust(\n existingFolderIndex,\n R.mergeLeft({ sharedSchools: [], sharedUsers: [] }),\n myFolders\n )\n}\n","import R from 'ramda'\n\nimport actionTypes from './actionTypes'\n\nimport addNewFolder from './helpers/addNewFolder'\nimport adjustFolder from './helpers/adjustFolder'\nimport replaceChangedFolders from './helpers/replaceChangedFolders'\nimport withoutFolderId from './helpers/withoutFolderId'\nimport withoutFolderItem from './helpers/withoutFolderItem'\nimport {\n addPublishedFolder,\n removePublishedFolder,\n withFolderPublished,\n withFolderUnpublished,\n} from './helpers/publishedFolders'\nimport { adjustFolderShares, removeFolderShares } from './helpers/sharedFolders'\n\nexport default function foldersReducer(state, action) {\n const { type, payload } = action\n\n return R.cond([\n [\n R.equals(actionTypes.setFolders),\n () => ({ ...state, myFolders: payload }),\n ],\n [\n R.equals(actionTypes.setCurrentFolderId),\n () => ({ ...state, currentFolderId: payload }),\n ],\n [\n R.equals(actionTypes.createFolder),\n () => ({\n ...state,\n myFolders: addNewFolder(payload, state.myFolders),\n }),\n ],\n [\n R.equals(actionTypes.updateFolder),\n () => ({\n ...state,\n myFolders: adjustFolder(\n {\n id: payload.id,\n name: payload.name,\n description: payload.description,\n },\n state.myFolders\n ),\n }),\n ],\n [\n R.equals(actionTypes.updateChangedFolders),\n () => ({\n ...state,\n myFolders: replaceChangedFolders({\n changedFolders: payload,\n folders: state.myFolders,\n }),\n }),\n ],\n [\n R.equals(actionTypes.addPublishedFolder),\n () => ({\n ...state,\n myFolders: withFolderPublished({\n folderId: payload.id,\n eslPublishedAt: payload.eslPublishedAt,\n myFolders: state.myFolders,\n }),\n publishedFolders: addPublishedFolder({\n folder: payload,\n publishedFolders: state.publishedFolders,\n }),\n }),\n ],\n [\n R.equals(actionTypes.removePublishedFolder),\n () => ({\n ...state,\n myFolders: withFolderUnpublished({\n folderId: payload,\n myFolders: state.myFolders,\n }),\n publishedFolders: removePublishedFolder({\n folderId: payload,\n publishedFolders: state.publishedFolders,\n }),\n }),\n ],\n [\n R.equals(actionTypes.adjustFolderShares),\n () => ({\n ...state,\n myFolders: adjustFolderShares({\n folder: payload,\n myFolders: state.myFolders,\n }),\n }),\n ],\n [\n R.equals(actionTypes.removeFolderShares),\n () => ({\n ...state,\n myFolders: removeFolderShares({\n folderId: payload,\n myFolders: state.myFolders,\n }),\n }),\n ],\n [\n R.equals(actionTypes.deleteFolder),\n () => ({\n ...state,\n myFolders: withoutFolderId(payload, state.myFolders),\n }),\n ],\n [\n R.equals(actionTypes.deleteFolderItem),\n () => ({\n ...state,\n myFolders: withoutFolderItem(\n {\n folderId: payload.folderId,\n itemId: payload.itemId,\n },\n state.myFolders\n ),\n }),\n ],\n [\n R.equals(actionTypes.setNewPublished),\n () => ({\n ...state,\n hasNewPublished: payload,\n }),\n ],\n [\n R.equals(actionTypes.setNewShared),\n () => ({\n ...state,\n hasNewShared: payload,\n }),\n ],\n [\n R.equals(actionTypes.sortAscending),\n () => ({\n ...state,\n sort: payload,\n }),\n ],\n [\n R.equals(actionTypes.sortDescending),\n () => ({\n ...state,\n sort: payload,\n }),\n ],\n [\n R.equals(actionTypes.sortManual),\n () => ({\n ...state,\n sort: payload,\n }),\n ],\n [\n R.equals(actionTypes.sortSharedAscending),\n () => ({\n ...state,\n sharedSort: payload,\n }),\n ],\n [\n R.equals(actionTypes.sortSharedAuthor),\n () => ({\n ...state,\n sharedSort: payload,\n }),\n ],\n [\n R.equals(actionTypes.sortSharedDate),\n () => ({\n ...state,\n sharedSort: payload,\n }),\n ],\n [\n R.equals(actionTypes.sortSharedDescending),\n () => ({\n ...state,\n sharedSort: payload,\n }),\n ],\n [\n R.T,\n () => {\n throw new Error(`Unhandled action type: ${type}`)\n },\n ],\n ])(type)\n}\n","import R from 'ramda'\n\n/**\n * Add a newly created folder to the user's folders\n * @param {Object} folder - The new folder returned by the endpoint\n * @param {Array} folders - The array of folders from the current state\n */\nexport default function addNewFolder(folder, folders) {\n // Increment each existing folder's position (the new folder comes back with position: 1)\n const repositionedFolders = folders.map(f => ({\n ...f,\n position: R.inc(f.position),\n }))\n\n // Prepend the new folder to the repositioned folders\n // NB: It actually doesn't matter if we prepend or append the new folder to the folders array,\n // since manual sorting looks at position properties and not array indexes.\n // R.prepend is only used here to be thematically consistent.\n return R.prepend(folder, repositionedFolders)\n}\n","import R from 'ramda'\n\n/**\n * Update multiple folders with new copies\n * (folder items endpoint returns all changed folders\n * when an item is moved to/from folder(s))\n * @param {Object} config - The configuration object\n * @param {Array} config.changedFolders - The list of changed folders as returned from the endpoint\n * @param {Array} folders - The array of folders from the current state\n */\nexport default function replaceChangedFolders({ changedFolders, folders }) {\n // create a copy of the existing folders array\n let mergedFolders = folders\n\n const replaceFolder = changedFolder => {\n // get the index of the changedFolder in mergedFolders\n const indexFromMerged = R.findIndex(\n R.propEq('id', changedFolder.id),\n mergedFolders\n )\n if (indexFromMerged < 0)\n throw new Error(\n `replaceFolder: id ${changedFolder.id} not found in mergedFolders`\n )\n\n // replace the existing folder with the changedFolder\n // yes, gross object mutation, I know (;__;)\n mergedFolders = R.update(indexFromMerged, changedFolder, mergedFolders)\n }\n\n // Run replaceFolder for every folder in changedFolders\n changedFolders.map(replaceFolder)\n\n // return the gross mutated array\n return mergedFolders\n}\n","export const foldersEndpoint = `/api/v1/folders`\nexport const folderItemsEndpoint = `/api/v1/folder_items`\n","import xhr from 'Common/utils/xhr'\nimport { foldersEndpoint } from './endpoints'\n\n/**\n * Create a folder\n * @param {Object} config\n * @param {string} [config.name=null] - The name of the new folder; endpoint returns 'Untitled Folder' by default\n * @param {string} [config.description=null] - The folder description; endpoint returns null by default\n * @param {(Object|Boolean)} [config.item=false] - A folder item object to instantiate the folder with\n */\nconst createFolder = ({ name = null, description = null, item = false } = {}) =>\n xhr({\n url: foldersEndpoint,\n method: 'POST',\n data: {\n folder: {\n name,\n description,\n ...(item && {\n folder_items_attributes: [\n {\n fileable_id: item.fileable.id,\n fileable_type: item.fileable.type,\n },\n ],\n }),\n },\n },\n })\n\nexport default createFolder\n","import copyFolder from './copyFolder'\nimport createFolder from './createFolder'\nimport deleteFolder from './deleteFolder'\nimport deleteItem from './deleteItem'\nimport getFolderContent from './getFolderContent'\nimport getFolders from './getFolders'\nimport publishFolder from './publishFolder'\nimport putItem from './putItem'\nimport sendFolderNotification from './sendFolderNotification'\nimport shareFolder from './shareFolder'\nimport unpublishFolder from './unpublishFolder'\nimport unshareFolder from './unshareFolder'\nimport updateFolder from './updateFolder'\nimport updateFolderPosition from './updateFolderPosition'\nimport updateItemPosition from './updateItemPosition'\n\nexport default {\n copyFolder,\n createFolder,\n deleteFolder,\n deleteItem,\n getFolderContent,\n getFolders,\n publishFolder,\n putItem,\n sendFolderNotification,\n shareFolder,\n unpublishFolder,\n unshareFolder,\n updateFolder,\n updateFolderPosition,\n updateItemPosition,\n}\n","import xhr from 'Common/utils/xhr'\nimport { foldersEndpoint } from './endpoints'\n\n/**\n * Copies a folder to the current user's own folders\n * @param {number} id - The ID of the folder to be copied\n */\nconst copyFolder = id =>\n xhr({\n url: `${foldersEndpoint}/${id}/copy`,\n method: 'POST',\n })\n\nexport default copyFolder\n","import xhr from 'Common/utils/xhr'\nimport { foldersEndpoint } from './endpoints'\n\nconst deleteFolder = id =>\n xhr({\n url: `${foldersEndpoint}/${id}`,\n method: 'DELETE',\n })\n\nexport default deleteFolder\n","import xhr from 'Common/utils/xhr'\nimport { folderItemsEndpoint } from './endpoints'\n\nconst deleteItem = itemId =>\n xhr({\n url: `${folderItemsEndpoint}/${itemId}`,\n method: 'DELETE',\n })\n\nexport default deleteItem\n","import xhr from 'Common/utils/xhr'\nimport { foldersEndpoint } from './endpoints'\n\nconst getFolderContent = id =>\n xhr({\n url: `${foldersEndpoint}/${id}`,\n method: 'GET',\n })\n\nexport default getFolderContent\n","import xhr from 'Common/utils/xhr'\nimport { foldersEndpoint } from './endpoints'\n\nconst getFolders = () =>\n xhr({\n url: foldersEndpoint,\n method: 'GET',\n })\n\nexport default getFolders\n","import xhr from 'Common/utils/xhr'\nimport { foldersEndpoint } from './endpoints'\n\n/**\n * Publish a folder (ESL Folders account only; makes it visible under Ellii Folders)\n * @param {Object} config\n * @param {number} config.id - The folder ID\n * @param {string} config.publishedAt - ISO datetime string to for when the folder was published\n */\nconst publishFolder = ({ id, publishedAt }) =>\n xhr({\n url: `${foldersEndpoint}/${id}`,\n method: 'PUT',\n data: {\n folder: {\n esl_published_at: publishedAt,\n },\n },\n })\n\nexport default publishFolder\n","import xhr from 'Common/utils/xhr'\nimport { folderItemsEndpoint } from './endpoints'\n\n/**\n * Put an item into one or more folders\n * @param {Object} config\n * @param {number} config.fileableId - The fileable ID of the folder item\n * @param {string} config.fileableType - The fileable type of the folder item\n * @param {number[]} config.inFolders - The list of folder IDs to place the folder item in\n */\nconst putItem = ({ fileableId, fileableType, inFolders }) =>\n xhr({\n url: `${folderItemsEndpoint}/move`,\n method: 'PUT',\n data: {\n folders: inFolders,\n folder_item: {\n fileable_id: fileableId,\n fileable_type: fileableType,\n },\n },\n })\n\nexport default putItem\n","import xhr from 'Common/utils/xhr'\nimport { foldersEndpoint } from './endpoints'\n\n/**\n * Triggers the creation of a folder notification\n * @param {number} id - The ID of the folder to create the notification\n */\nconst sendFolderNotification = id =>\n xhr({\n url: `${foldersEndpoint}/${id}/send_notification`,\n method: 'POST',\n })\n\nexport default sendFolderNotification\n","import xhr from 'Common/utils/xhr'\nimport { foldersEndpoint } from './endpoints'\n\n/**\n * Share a folder with a school, or with users. Presently only one school may be\n * shared with, but this may change in future (hence it being an array of school ids).\n * Note that if the schools array is populated, the users array should be empty,\n * and vice versa — you cannot share a folder both with a school and individual users.\n * Both arrays may be empty at once to clear any previous shares.\n * @param {Object} config\n * @param {number} config.id - The id of the folder to share\n * @param {number[]} config.schools - Array of schools ids to share the folder with\n * @param {numberp[]} config.users - Array of user ids to share the folder with\n */\nconst shareFolder = ({ id, schools, users }) =>\n xhr({\n url: `${foldersEndpoint}/${id}/share`,\n method: 'POST',\n data: {\n schools,\n users,\n },\n })\n\nexport default shareFolder\n","import xhr from 'Common/utils/xhr'\nimport { foldersEndpoint } from './endpoints'\n\n/**\n * Unpublish a folder (ESL Folders account only)\n * @param {number} id - The folder ID\n */\nconst unpublishFolder = id =>\n xhr({\n url: `${foldersEndpoint}/${id}`,\n method: 'PUT',\n data: {\n folder: {\n esl_published_at: null,\n },\n },\n })\n\nexport default unpublishFolder\n","import xhr from 'Common/utils/xhr'\nimport { foldersEndpoint } from './endpoints'\n\n/**\n * Removes any sharing associations from a folder\n * @param {number} id - The id of the folder to unshare\n */\nconst unshareFolder = id =>\n xhr({\n url: `${foldersEndpoint}/${id}/unshare`,\n method: 'DELETE',\n })\n\nexport default unshareFolder\n","import xhr from 'Common/utils/xhr'\nimport { foldersEndpoint } from './endpoints'\n\n/**\n * Update a folder's name and/or description\n * @param {Object} config\n * @param {number} config.id - The folder ID\n * @param {string} config.name - The folder name to be used\n * @param {string} config.description - The folder description to be used\n */\nconst updateFolder = ({ id, name, description }) =>\n xhr({\n url: `${foldersEndpoint}/${id}`,\n method: 'PUT',\n data: {\n folder: {\n name,\n description,\n },\n },\n })\n\nexport default updateFolder\n","import xhr from 'Common/utils/xhr'\nimport { foldersEndpoint } from './endpoints'\n\n/**\n * Update a folder's position in the sort order\n * @param {Object} config\n * @param {number} config.id - The folder ID\n * @param {number} config.position - The new position for the folder; positions are 1-based\n */\nconst updateFolderPosition = ({ id, position }) =>\n xhr({\n url: `${foldersEndpoint}/${id}`,\n method: 'PUT',\n data: {\n folder: {\n position,\n },\n },\n })\n\nexport default updateFolderPosition\n","import xhr from 'Common/utils/xhr'\nimport { folderItemsEndpoint } from './endpoints'\n\n/**\n * Update a folder item's position in the sort order\n * @param {Object} config\n * @param {number} config.id - The folder item ID\n * @param {number} config.position - The new position for the folder item; positions are 1-based\n */\nconst updateItemPosition = ({ id, position }) =>\n xhr({\n url: `${folderItemsEndpoint}/${id}`,\n method: 'PUT',\n data: {\n folder_item: {\n position,\n },\n },\n })\n\nexport default updateItemPosition\n","import PropTypes from 'prop-types'\nimport R from 'ramda'\nimport { createContext, useContext, useEffect, useReducer } from 'react'\n\nimport getInitialState from 'Common/utils/getInitialState'\nimport useUserAccess from 'Common/hooks/useUserAccess'\n\nimport actions from './actions'\nimport foldersReducer from './reducer'\nimport services from '../services'\n\n// Context objects\nconst FoldersState = createContext()\nconst FoldersDispatch = createContext()\n\nFoldersState.displayName = 'FoldersState'\nFoldersDispatch.displayName = 'FoldersDispatch'\n\n// Context hook\nfunction useFoldersContext() {\n const state = useContext(FoldersState)\n const dispatch = useContext(FoldersDispatch)\n\n if (state === undefined || dispatch === undefined) {\n throw new Error('useFoldersContext must be used within a FoldersProvider')\n }\n\n return [state, dispatch]\n}\n\nfunction FoldersProvider({ children }) {\n const {\n myFolders,\n publishedFolders,\n sharedFolders,\n school,\n users,\n } = getInitialState()\n\n const initialState = {\n myFolders,\n publishedFolders,\n sharedFolders,\n school,\n users,\n currentFolderId: null, // Will be updated by WatchCurrentFolder in Folders app; otherwise not used\n hasNewPublished: false,\n hasNewShared: false,\n isPublisher: R.any(R.has('eslPublishedAt'), myFolders),\n sort: 'manual',\n sharedSort: 'ascending',\n }\n\n const [foldersState, setFoldersState] = useReducer(\n foldersReducer,\n initialState\n )\n\n return (\n \n \n {children}\n \n \n )\n}\n\nFoldersProvider.propTypes = {\n children: PropTypes.node.isRequired,\n}\n\n// Context provider for the MoveItemModal used on content pages with Rails-based initial state\nfunction ModalFoldersProvider({ children }) {\n // Initial state on site content pages renders only\n // user's folders, so we don't need to destructure myFolders\n // from the initial state.\n const folders = getInitialState()\n\n const initialState = {\n myFolders: folders,\n }\n\n const [foldersState, setFoldersState] = useReducer(\n foldersReducer,\n initialState\n )\n\n return (\n \n \n {children}\n \n \n )\n}\n\nModalFoldersProvider.propTypes = {\n children: PropTypes.node.isRequired,\n}\n\n// Context provider for the MoveItemModal used on content pages with API-based initial state\n// `fallback` node will be rendered until folders have been fetched\nfunction AsyncModalFoldersProvider({ fallback, children }) {\n // [1]\n // We need to store the initial state as a variable so we can compare referential equality (see [2]).\n // (This avoids the use of a useState just for tracking whether the fetch has completed or not.)\n const initialFolders = []\n const { userLoggedIn } = useUserAccess()\n\n const [foldersState, setFoldersState] = useReducer(foldersReducer, {\n myFolders: initialFolders,\n userLoggedIn,\n })\n\n // Fetch the user's folders when the Provider first mounts\n useEffect(() => {\n async function fetchFolders() {\n const { data: fetchedFolders } = await services.getFolders()\n return setFoldersState(actions.setFolders(fetchedFolders))\n }\n\n userLoggedIn && fetchFolders()\n }, [userLoggedIn])\n\n // [2]\n // If the folders haven't been fetched yet, display the fallback.\n // If the state is referentially equal to our initial empty state, the fetch hasn't been completed yet.\n if (foldersState.myFolders === initialFolders) {\n return fallback\n }\n\n return (\n \n \n {children}\n \n \n )\n}\n\nAsyncModalFoldersProvider.propTypes = {\n children: PropTypes.node.isRequired,\n fallback: PropTypes.node.isRequired,\n}\n\nexport {\n FoldersProvider,\n ModalFoldersProvider,\n AsyncModalFoldersProvider,\n useFoldersContext,\n}\n","import PropTypes from 'prop-types'\n\nimport FolderOpen from 'Images/folders/folder-open.svg'\nimport { Box, Image, Heading } from '@redriverpress/system'\n\nexport default function EmptyState({ action, message }) {\n return (\n \n \n \n {message}\n \n {action && action}\n \n )\n}\n\nEmptyState.defaultProps = {\n action: null,\n}\n\nEmptyState.propTypes = {\n action: PropTypes.node,\n message: PropTypes.string.isRequired,\n}\n","import R from 'ramda'\n\n// FILEABLE NAME\nconst ascByFileableName = R.ascend(R.path(['fileable', 'name']))\nconst descByFileableName = R.descend(R.path(['fileable', 'name']))\n\n// POSITIONS\nconst ascByPosition = R.ascend(R.prop('position'))\nconst ascByFileablePosition = R.ascend(R.path(['fileable', 'position']))\n\n// SHARED\n\n// Sort first by author name, then name of folder\nconst ascByAuthor = [R.ascend(R.prop('authorName')), R.ascend(R.prop('name'))]\n\n// Sort first by most recent date, then by name of folder\nconst descByDate = [R.descend(R.prop('sharedAt')), R.ascend(R.prop('name'))]\n\nexport default {\n ascByFileableName,\n descByFileableName,\n ascByPosition,\n ascByFileablePosition,\n ascByAuthor,\n descByDate,\n}\n","/**\n * This modal allows a user to select which of their folders the item should be in.\n * The folders it's already in will be selected by default; they can uncheck those folders to remove it.\n * They can also create a new folder in this modal, give it a name (default is 'Untitled Folder'),\n * and place the item in that folder (though the new folder will be saved whether they place the item\n * in that folder or not.)\n */\nimport PropTypes from 'prop-types'\nimport {\n allPass,\n any,\n assoc,\n equals,\n find,\n last,\n pathEq,\n prepend,\n propEq,\n sort,\n without,\n} from 'ramda'\nimport { Fragment, useEffect, useRef, useState } from 'react'\n\nimport {\n Box,\n Button,\n CheckboxControl,\n Dialog,\n HR,\n Heading,\n Icon,\n Image,\n LoadingSpinner,\n SimpleInput,\n Text,\n} from '@redriverpress/system'\nimport FolderOpen from 'Images/folders/folder-open.svg'\nimport useDidMountEffect from 'Common/hooks/useDidMountEffect'\n\nimport folderSorts from '../utils/sort'\nimport services from '../services'\nimport { actions, useFoldersContext } from '../context'\n\n/* This component lends several patterns to SaveSelectionDialog.js.\n * Changes to one component may need to be reflected in the other.\n */\nexport default function MoveItemModal({ isOpen, onClose, item, onMoveItem }) {\n const [{ myFolders }, dispatchFolders] = useFoldersContext()\n const sortedFolders = sort(folderSorts.ascByPosition, myFolders)\n\n // Initialize `selection` as an object, whose keys are the id of each folder,\n // and whose value is true if that folder contains the item's fileable ID and type already\n const initialSelection = sortedFolders.reduce(\n (fs, f) =>\n assoc(\n f.id,\n f.folderItems // empty folders have no folderItems\n ? any(\n allPass([\n pathEq(['fileable', 'id'], item.fileable.id),\n pathEq(['fileable', 'type'], item.fileable.type),\n ]),\n f.folderItems\n )\n : false,\n fs\n ),\n {}\n )\n\n // Selection is an object whose keys are folder IDs\n // and values are booleans indicating the check status of that folder\n const [selection, setSelection] = useState(initialSelection)\n const toggleFolderSelection = folderId =>\n setSelection(assoc(folderId, !selection[folderId], selection))\n\n useEffect(() => {\n // Set the selection back to initialSelection whenever the modal opens/closes.\n // The avoids unsaved changes in the selection persisting across opening/closing.\n setSelection(initialSelection)\n }, [isOpen])\n\n // Array of IDs of new folders made since opening the modal\n // (Persists across open/close, but not across rerenders)\n const [newFolderIds, setNewFolderIds] = useState([])\n\n // currentFolders are the sorted folders which existed when\n // the MoveItemModal was last rendered (opening/closing doesn't rerender!)\n const currentFolders = sortedFolders.filter(f => !newFolderIds.includes(f.id))\n\n // newFolders is sortedFolders without currentFolders\n const newFolders = without(currentFolders, myFolders)\n\n const newFolderRef = useRef(null)\n const [namingNewFolder, setNamingNewFolder] = useState(false)\n\n const [isNameError, setIsNameError] = useState(false)\n\n // When clicking the New Folder button:\n // 1. Show a spinner in the New Folder button\n // 2. Request new folder from BE\n // 3. Put new folder in context\n // 4. Add new folder's ID to newFolderIDs\n // 5. Toggle state for naming new folder\n // 6. Focus the new folder's name input (this step won't work on iOS)\n const handleNewFolder = async () => {\n const { data: newFolder } = await services.createFolder({\n name: 'ellii_temp_default',\n })\n dispatchFolders(actions.createFolder(newFolder))\n setNewFolderIds(current => prepend(newFolder.id, current))\n setSelection({ ...selection, [newFolder.id]: true })\n newFolderRef.current.focus()\n }\n\n const handleFolderRename = async ({ id, name }) => {\n if (!name) return setIsNameError(true)\n\n const { data: updatedFolder } = await services.updateFolder({\n id,\n name,\n description: '',\n })\n dispatchFolders(actions.updateFolder(updatedFolder))\n setNamingNewFolder(false)\n }\n\n const [movePending, setMovePending] = useState(false)\n const handleMove = async () => {\n if (namingNewFolder) return setIsNameError(true)\n setMovePending(true)\n\n // Filter folder IDs which map to `true` in `selection`\n // to determine which folders the item should now be in\n const inFolders = Object.keys(selection)\n .filter(f => selection[f])\n .map(id => Number(id))\n\n const { data: changedFolders } = await services.putItem({\n inFolders,\n fileableId: item.fileable.id,\n fileableType: item.fileable.type,\n })\n\n setMovePending(false)\n dispatchFolders(actions.updateChangedFolders(changedFolders))\n onMoveItem && onMoveItem(!!inFolders.length)\n setIsNameError(false)\n onClose(!!newFolders.length)\n }\n\n // Don't allow modal to close when any of these conditions are true\n const shouldNotClose = any(x => Boolean(x), [movePending, namingNewFolder])\n\n const handleClose = () => {\n if (isOpen || shouldNotClose) return\n\n setSelection(initialSelection)\n setNewFolderIds([])\n setIsNameError(false)\n onClose()\n }\n\n // If the user reloads the page or cancels\n // the 'new folder' process instead of\n // saving, this method will remove the folder\n // that was created\n const removeDisposedFolders = ids => {\n const tempFolder = myFolders.find(\n folder => folder.name === 'ellii_temp_default'\n )\n if (tempFolder) {\n dispatchFolders(actions.deleteFolder(tempFolder.id))\n setNewFolderIds(\n newFolderIds.filter(folderId => tempFolder.id !== folderId)\n )\n services.deleteFolder(tempFolder.id)\n } else if (ids?.length) {\n ids.forEach(id => {\n dispatchFolders(actions.deleteFolder(id))\n setNewFolderIds(newFolderIds.filter(folderId => id !== folderId))\n services.deleteFolder(id)\n })\n }\n }\n\n const cancelNewFolderBeforeClose = () => {\n if (newFolders) {\n removeDisposedFolders(newFolders.map(folder => folder.id))\n setNamingNewFolder(false)\n setIsNameError(false)\n onClose(!!newFolders.length)\n }\n }\n\n // only triggers 'handleNewFolder' if namingFolder is set 'true'\n useEffect(() => {\n if (namingNewFolder) {\n handleNewFolder()\n }\n }, [namingNewFolder])\n\n useDidMountEffect(() => {\n if (!namingNewFolder) {\n removeDisposedFolders()\n }\n }, [myFolders])\n\n return (\n \n \n \n {\n e.preventDefault()\n if (!newFolders.length) handleClose()\n }}\n >\n \n \n Save to…\n \n \n\n {!myFolders.length ? (\n \n \n \n You have no folders\n \n \n ) : (\n <>\n \n Check to add content or uncheck to remove content from\n folder(s).\n \n {isNameError && (\n \n \n \n Folder’s name can’t be blank.\n \n \n )}\n \n {/* List new folders before the rest of the folders */}\n {newFolderIds.map(newId => {\n const folder = find(propEq('id', newId), newFolders)\n return (\n \n \n \n toggleFolderSelection(folder.id)}\n />\n \n {/* Render an input if this folder is the most recent new folder\n and namingNewFolder is true */}\n {folder.id === newFolderIds[0] && namingNewFolder ? (\n e.target.select()}\n onKeyDown={e =>\n e.keyCode === 13 &&\n handleFolderRename({\n id: folder.id,\n name: e.target.value,\n })\n }\n onBlur={e =>\n handleFolderRename({\n id: folder.id,\n name: e.target.value,\n })\n }\n />\n ) : (\n \n {folder.name}\n \n )}\n \n {/* Don't render an HR under this folder if it's the last one in the newFolders\n and there are no currentFolders (results in a double bottom border w/ wrapping box) */}\n {!currentFolders.length &&\n equals(folder, last(newFolders)) ? null : (\n
\n )}\n
\n )\n })}\n {currentFolders.map(folder => (\n \n \n \n toggleFolderSelection(folder.id)}\n />\n \n \n {folder.name}\n \n \n {!equals(folder, last(currentFolders)) && (\n
\n )}\n
\n ))}\n \n \n )}\n\n \n setNamingNewFolder(true)}\n disabled={movePending || namingNewFolder}\n >\n \n New Folder\n \n \n\n \n \n \n Cancel\n \n\n \n {movePending ? : }\n \n Save\n \n \n \n \n \n
\n \n )\n}\n\nMoveItemModal.defaultProps = {\n onMoveItem: null,\n}\n\nMoveItemModal.propTypes = {\n isOpen: PropTypes.bool.isRequired,\n item: PropTypes.shape({\n fileable: PropTypes.shape({\n id: PropTypes.number.isRequired,\n type: PropTypes.string.isRequired,\n }).isRequired,\n }).isRequired,\n onClose: PropTypes.func.isRequired,\n onMoveItem: PropTypes.func,\n}\n"],"sourceRoot":""}