| @@ -9,24 +9,56 @@ import { | |||
| } from "@mui/material"; | |||
| import filterIcon from "../../assets/images/filter_vector.png"; | |||
| import x from "../../assets/images/x.png"; | |||
| import { useSelector } from "react-redux"; | |||
| // const tags = [ | |||
| // { name: ".txt", isChecked: false }, | |||
| // { name: ".pdf", isChecked: true }, | |||
| // { name: ".docx", isChecked: true }, | |||
| // ]; | |||
| import { useDispatch, useSelector } from "react-redux"; | |||
| import { | |||
| getFilesReq, | |||
| updateFileFilterCat, | |||
| updateFileFilterExt, | |||
| updateFileFilterTag, | |||
| } from "../../store/actions/files/fileActions"; | |||
| const DocsFilters = ({ open, handleClose }) => { | |||
| const DocsFilters = ({ open, handleClose, setPage }) => { | |||
| const dispatch = useDispatch(); | |||
| const { filters } = useSelector((s) => s.fileFilters); | |||
| const handleCheckboxes = (e) => { | |||
| const { value } = e.target; | |||
| console.log(value); | |||
| }; | |||
| const handleCheckboxesExt = (e) => | |||
| dispatch(updateFileFilterExt(e.target.value)); | |||
| const handleCheckboxesTags = (e) => | |||
| dispatch(updateFileFilterTag(e.target.value)); | |||
| const handleCheckboxesCat = (e) => | |||
| dispatch(updateFileFilterCat(e.target.value)); | |||
| const submitFiltersHandler = (e) => { | |||
| e.preventDefault(); | |||
| var catFilters = []; | |||
| filters.categories | |||
| ?.filter((n) => n.isChecked) | |||
| .forEach((m) => catFilters.push(m.name)); | |||
| var extFilters = []; | |||
| filters.extensions | |||
| ?.filter((n) => n.isChecked) | |||
| .forEach((m) => extFilters.push(m.name)); | |||
| var tagFilters = []; | |||
| filters.tags | |||
| ?.filter((n) => n.isChecked) | |||
| .forEach((m) => tagFilters.push(m.name)); | |||
| const submitFiltersHandler = () => { | |||
| alert("Pamet u glavu"); | |||
| dispatch( | |||
| getFilesReq({ | |||
| payload: { | |||
| pageSize: 6, | |||
| currentPage: 1, | |||
| categories: catFilters, | |||
| extensions: extFilters, | |||
| tags: tagFilters, | |||
| }, | |||
| apiSuccess: handleClose, | |||
| }) | |||
| ); | |||
| setPage(1); | |||
| }; | |||
| const list = () => ( | |||
| @@ -69,7 +101,7 @@ const DocsFilters = ({ open, handleClose }) => { | |||
| key={index} | |||
| control={ | |||
| <Checkbox | |||
| onChange={handleCheckboxes} | |||
| onChange={handleCheckboxesExt} | |||
| value={tag.name} | |||
| checked={tag.isChecked} | |||
| className="ad-filters-checkbox" | |||
| @@ -93,7 +125,7 @@ const DocsFilters = ({ open, handleClose }) => { | |||
| key={index} | |||
| control={ | |||
| <Checkbox | |||
| onChange={handleCheckboxes} | |||
| onChange={handleCheckboxesTags} | |||
| value={tag.name} | |||
| checked={tag.isChecked} | |||
| className="ad-filters-checkbox" | |||
| @@ -117,7 +149,7 @@ const DocsFilters = ({ open, handleClose }) => { | |||
| key={index} | |||
| control={ | |||
| <Checkbox | |||
| onChange={handleCheckboxes} | |||
| onChange={handleCheckboxesCat} | |||
| value={tag.name} | |||
| checked={tag.isChecked} | |||
| className="ad-filters-checkbox" | |||
| @@ -160,6 +192,7 @@ const DocsFilters = ({ open, handleClose }) => { | |||
| DocsFilters.propTypes = { | |||
| open: PropType.any, | |||
| handleClose: PropType.func, | |||
| setPage: PropType.func, | |||
| }; | |||
| export default DocsFilters; | |||
| @@ -1,3 +1,4 @@ | |||
| import { Pagination } from "@mui/material"; | |||
| import React from "react"; | |||
| import { useEffect } from "react"; | |||
| import { useState } from "react"; | |||
| @@ -5,11 +6,18 @@ import { useSelector } from "react-redux"; | |||
| import { useDispatch } from "react-redux"; | |||
| import FilterButton from "../../components/Button/FilterButton"; | |||
| import DocsFilters from "../../components/Docs/DocsFilters"; | |||
| import { getFileFiltersReq, getFilesReq } from "../../store/actions/files/fileActions"; | |||
| import { FETCH_FILES_LOADING } from "../../store/actions/files/fileActionConstants"; | |||
| import { | |||
| getFileFiltersReq, | |||
| getFilesReq, | |||
| } from "../../store/actions/files/fileActions"; | |||
| import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors"; | |||
| const FilesViewPage = () => { | |||
| const [toggleFiltersDrawer, setToggleFiltersDrawer] = useState(false); | |||
| const {files} = useSelector(s => s.files) | |||
| const [page, setPage] = useState(1) | |||
| const { filters } = useSelector((s) => s.fileFilters); | |||
| const { data } = useSelector((s) => s.files); | |||
| const dispatch = useDispatch(); | |||
| @@ -19,20 +27,69 @@ const FilesViewPage = () => { | |||
| useEffect(() => { | |||
| dispatch(getFileFiltersReq()); | |||
| dispatch( | |||
| getFilesReq({ | |||
| payload: { | |||
| pageSize: 6, | |||
| currentPage: page, | |||
| categories: [], | |||
| extensions: [], | |||
| tags: [], | |||
| }, | |||
| }) | |||
| ); | |||
| }, []); | |||
| // disjoin the effect because we want the metods to trigger on different occassions | |||
| useEffect(() => { | |||
| dispatch(getFilesReq()); | |||
| }, []); | |||
| const handleChange = (_, value) => { | |||
| var catFilters = []; | |||
| filters.categories | |||
| ?.filter((n) => n.isChecked) | |||
| .forEach((m) => catFilters.push(m.name)); | |||
| var extFilters = []; | |||
| filters.extensions | |||
| ?.filter((n) => n.isChecked) | |||
| .forEach((m) => extFilters.push(m.name)); | |||
| var tagFilters = []; | |||
| filters.tags | |||
| ?.filter((n) => n.isChecked) | |||
| .forEach((m) => tagFilters.push(m.name)); | |||
| return ( | |||
| dispatch( | |||
| getFilesReq({ | |||
| payload: { | |||
| pageSize: 6, | |||
| currentPage: value, | |||
| categories: catFilters, | |||
| extensions: extFilters, | |||
| tags: tagFilters, | |||
| }, | |||
| }) | |||
| ); | |||
| setPage(value); | |||
| }; | |||
| const isLoading = useSelector( | |||
| selectIsLoadingByActionType(FETCH_FILES_LOADING) | |||
| ); | |||
| return isLoading ? ( | |||
| <div> | |||
| <div className="l-t-rectangle"></div> | |||
| <div className="r-b-rectangle"></div> | |||
| <div className="loader-container h-withHeader"> | |||
| <span>Loading</span> | |||
| </div> | |||
| </div> | |||
| ) : ( | |||
| <div> | |||
| <div className="l-t-rectangle"></div> | |||
| <div className="r-b-rectangle"></div> | |||
| <DocsFilters | |||
| open={toggleFiltersDrawer} | |||
| handleClose={handleToggleFiltersDrawer} | |||
| setPage = {setPage} | |||
| /> | |||
| <div | |||
| // onClick={() => setIsSearchFieldVisible(false)} | |||
| @@ -96,8 +153,8 @@ const FilesViewPage = () => { | |||
| </thead> | |||
| <tbody> | |||
| {files?.map((n) => ( | |||
| <tr key={n.id} className="secondaryRow"> | |||
| {data.data?.length > 0 && data.data?.map((n) => ( | |||
| <tr key={n.id + n.name} className="secondaryRow"> | |||
| <td className="docs-name">{n.name}</td> | |||
| <td>{n.extension}</td> | |||
| <td className="profession">{n.size}kB</td> | |||
| @@ -106,6 +163,20 @@ const FilesViewPage = () => { | |||
| ))} | |||
| </tbody> | |||
| </table> | |||
| <Pagination | |||
| // size={matches ? "small" : "medium"} | |||
| size={"small"} | |||
| count={ | |||
| parseInt(data.total) <= 6 | |||
| ? 1 | |||
| : Math.ceil(parseInt(data.total) / 6) | |||
| } | |||
| color="primary" | |||
| className="candidates-pagination" | |||
| onChange={handleChange} | |||
| shape="rounded" | |||
| page={page} | |||
| /> | |||
| </div> | |||
| <div | |||
| style={{ | |||
| @@ -80,6 +80,6 @@ export default { | |||
| }, | |||
| files:{ | |||
| uploadFile: base + "/files", | |||
| all: base + "/files" | |||
| all: base + "/files/filtered" | |||
| } | |||
| }; | |||
| @@ -1,4 +1,30 @@ | |||
| import { getRequest } from "."; | |||
| import apiEndpoints from "./apiEndpoints"; | |||
| export const getAllFilesReq = () => getRequest(apiEndpoints.files.all); | |||
| export const getAllFilesReq = (payload) => { | |||
| let categoryQuery = ""; | |||
| for (let i = 0; i < payload.categories.length; i++) { | |||
| categoryQuery += `&categories=${payload.categories[i]}`; | |||
| } | |||
| let tagQuery = ""; | |||
| for (let i = 0; i < payload.tags.length; i++) { | |||
| tagQuery += `&tags=${payload.tags[i]}&`; | |||
| } | |||
| let extQuery = ""; | |||
| for (let i = 0; i < payload.extensions.length; i++) { | |||
| extQuery += `&extensions=${payload.extensions[i]}`; | |||
| } | |||
| return getRequest( | |||
| apiEndpoints.files.all + | |||
| "?currentPage=" + | |||
| payload.currentPage + | |||
| "&pageSize=" + | |||
| payload.pageSize + | |||
| categoryQuery + | |||
| extQuery + | |||
| tagQuery | |||
| ); | |||
| }; | |||
| @@ -10,6 +10,9 @@ export const FILE_FILTERS_REQ = createFetchType(FILE_FILTERS_SCOPE); | |||
| export const FILE_FILTERS_ERR = createErrorType(FILE_FILTERS_SCOPE); | |||
| export const FILE_FILTERS_SUCCESS = createSuccessType(FILE_FILTERS_SCOPE); | |||
| export const FILE_FILTERS_LOADING = createLoadingType(FILE_FILTERS_SCOPE); | |||
| export const UPDATE_FILTERS_EXTENSION = 'UPDATE_FILTERS_EXTENSION'; | |||
| export const UPDATE_FILTERS_TAG = 'UPDATE_FILTERS_TAG'; | |||
| export const UPDATE_FILTERS_CATEGORY = 'UPDATE_FILTERS_CATEGORY'; | |||
| const FETCH_FILES_SCOPE = "FETCH_FILES"; | |||
| export const FETCH_FILES_REQ = createFetchType(FETCH_FILES_SCOPE); | |||
| @@ -1,10 +1,13 @@ | |||
| import { | |||
| FETCH_FILES_ERR, | |||
| FETCH_FILES_REQ, | |||
| FETCH_FILES_SUCCESS, | |||
| FETCH_FILES_ERR, | |||
| FETCH_FILES_REQ, | |||
| FETCH_FILES_SUCCESS, | |||
| FILE_FILTERS_ERR, | |||
| FILE_FILTERS_REQ, | |||
| FILE_FILTERS_SUCCESS, | |||
| UPDATE_FILTERS_CATEGORY, | |||
| UPDATE_FILTERS_EXTENSION, | |||
| UPDATE_FILTERS_TAG, | |||
| } from "./fileActionConstants"; | |||
| export const getFileFiltersReq = () => ({ | |||
| @@ -21,8 +24,22 @@ export const getFileFiltersSuccess = (payload) => ({ | |||
| payload, | |||
| }); | |||
| export const getFilesReq = () => ({ | |||
| export const updateFileFilterExt = (payload) => ({ | |||
| type: UPDATE_FILTERS_EXTENSION, | |||
| payload, | |||
| }); | |||
| export const updateFileFilterTag = (payload) => ({ | |||
| type: UPDATE_FILTERS_TAG, | |||
| payload, | |||
| }); | |||
| export const updateFileFilterCat = (payload) => ({ | |||
| type: UPDATE_FILTERS_CATEGORY, | |||
| payload, | |||
| }); | |||
| export const getFilesReq = (payload) => ({ | |||
| type: FETCH_FILES_REQ, | |||
| payload | |||
| }); | |||
| export const getFileError = (payload) => ({ | |||
| @@ -2,6 +2,9 @@ import createReducer from "../../utils/createReducer"; | |||
| import { | |||
| FILE_FILTERS_ERR, | |||
| FILE_FILTERS_SUCCESS, | |||
| UPDATE_FILTERS_CATEGORY, | |||
| UPDATE_FILTERS_EXTENSION, | |||
| UPDATE_FILTERS_TAG, | |||
| } from "../../actions/files/fileActionConstants"; | |||
| const initialState = { | |||
| @@ -13,6 +16,9 @@ export default createReducer( | |||
| { | |||
| [FILE_FILTERS_SUCCESS]: setFileFilters, | |||
| [FILE_FILTERS_ERR]: setFileFiltersErrorMessage, | |||
| [UPDATE_FILTERS_EXTENSION]: updateFileFilterExtension, | |||
| [UPDATE_FILTERS_TAG]: updateFileFilterTag, | |||
| [UPDATE_FILTERS_CATEGORY]: updateFileFilterCategory, | |||
| }, | |||
| initialState | |||
| ); | |||
| @@ -26,7 +32,10 @@ function setFileFilters(state, action) { | |||
| isChecked: false, | |||
| })), | |||
| tags: action.payload.tags.map((n) => ({ ...n, isChecked: false })), | |||
| extensions: action.payload.extensions.map((n) => ({ name: n, isChecked: false })), | |||
| extensions: action.payload.extensions.map((n) => ({ | |||
| name: n, | |||
| isChecked: false, | |||
| })), | |||
| }, | |||
| }; | |||
| } | |||
| @@ -37,3 +46,39 @@ function setFileFiltersErrorMessage(state, action) { | |||
| fetchFileFiltersErrorMessage: action.payload, | |||
| }; | |||
| } | |||
| function updateFileFilterExtension(state, action) { | |||
| return { | |||
| ...state, | |||
| filters: { | |||
| ...state.filters, | |||
| extensions: state.filters.extensions?.map((n) => | |||
| n.name === action.payload ? { ...n, isChecked: !n.isChecked } : n | |||
| ), | |||
| }, | |||
| }; | |||
| } | |||
| function updateFileFilterTag(state, action) { | |||
| return { | |||
| ...state, | |||
| filters: { | |||
| ...state.filters, | |||
| tags: state.filters.tags?.map((n) => | |||
| n.name === action.payload ? { ...n, isChecked: !n.isChecked } : n | |||
| ), | |||
| }, | |||
| }; | |||
| } | |||
| function updateFileFilterCategory(state, action) { | |||
| return { | |||
| ...state, | |||
| filters: { | |||
| ...state.filters, | |||
| categories: state.filters.categories?.map((n) => | |||
| n.name === action.payload ? { ...n, isChecked: !n.isChecked } : n | |||
| ), | |||
| }, | |||
| }; | |||
| } | |||
| @@ -5,7 +5,7 @@ import { | |||
| } from "../../actions/files/fileActionConstants"; | |||
| const initialState = { | |||
| files: [], | |||
| data: {}, | |||
| fetchFilesErrorMessage: "", | |||
| }; | |||
| @@ -20,7 +20,7 @@ export default createReducer( | |||
| function setFiles(state, action) { | |||
| return { | |||
| ...state, | |||
| files: action.payload, | |||
| data: action.payload, | |||
| }; | |||
| } | |||
| @@ -11,10 +11,7 @@ import { UPLOAD_FILE_REQ } from "../actions/uploadFile/uploadFileActionConstants | |||
| import { uploadFileRequest } from "../../request/filesRequest"; | |||
| import { getAllFilesReq } from "../../request/fileRequests"; | |||
| import { FETCH_FILES_REQ } from "../actions/files/fileActionConstants"; | |||
| import { | |||
| getFileError, | |||
| getFileSuccess, | |||
| } from "../actions/files/fileActions"; | |||
| import { getFileError, getFileSuccess } from "../actions/files/fileActions"; | |||
| export function* uploadFileSaga({ payload }) { | |||
| try { | |||
| @@ -22,8 +19,8 @@ export function* uploadFileSaga({ payload }) { | |||
| yield call(addHeaderToken, JwtToken); | |||
| const formData = new FormData(); | |||
| formData.append("categoryId", payload.categoryId); | |||
| for(let i = 0; i < payload.tagsIds.length; i++) | |||
| formData.append("tagsIds[]", payload.tagsIds[i]); | |||
| for (let i = 0; i < payload.tagsIds.length; i++) | |||
| formData.append("tagsIds[]", payload.tagsIds[i]); | |||
| formData.append("fileToUpload", payload.fileToUpload); | |||
| const result = yield call(uploadFileRequest, formData); | |||
| yield put(uploadFile(result.data)); | |||
| @@ -34,12 +31,13 @@ export function* uploadFileSaga({ payload }) { | |||
| } | |||
| } | |||
| export function* getAll() { | |||
| export function* getAll({ payload }) { | |||
| try { | |||
| const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN); | |||
| yield call(addHeaderToken, JwtToken); | |||
| const result = yield call(getAllFilesReq); | |||
| const result = yield call(getAllFilesReq, payload.payload); | |||
| yield put(getFileSuccess(result.data)); | |||
| if (payload.apiSuccess) yield call(payload.apiSuccess); | |||
| } catch (error) { | |||
| if (error.response && error.response.data) { | |||
| const errorMessage = yield call(rejectErrorCodeHelper, error); | |||