Przeglądaj źródła

Categories & deleting files changed

FE_dev
bronjaermin 2 lat temu
rodzic
commit
8f0548bdf6

+ 52
- 7
src/assets/styles/components/_files.scss Wyświetl plik

} }


.files-page-card { .files-page-card {
margin-bottom: 1.5rem;
}
margin-bottom: 1.5rem;
}


.files-page-card-title { .files-page-card-title {
margin-bottom: 1rem; margin-bottom: 1rem;
} }


.files-page-card-add-button { .files-page-card-add-button {
padding-bottom: 36px;
display: flex;
justify-content: space-between;
padding-bottom: 36px;
display: flex;
justify-content: space-between;
} }


.files-page-drag-and-drop { .files-page-drag-and-drop {
padding-right: 35px !important; padding-right: 35px !important;
} }


.search-field{
.search-field {
margin-right: 30px; margin-right: 30px;
margin-left: 0px; margin-left: 0px;
} }


.filesPage{
.filesPage {
align-self: flex-end; align-self: flex-end;
}

.files-page-categories {
display: flex;
flex-wrap: wrap;
}

.files-page-categories-category {
width: calc(100% / 4) !important;
margin: 0 !important;
padding: 16px;
}

.files-page-category-button {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 18px 72px;
gap: 10px;
width: 100%;
height: 100%;
background: #226cb0;
border-radius: 9px;
@include media-below($bp-xl) {
width: 147px;
}
}

.add-file-message {
display: flex;
align-items: center !important;
justify-content: center !important;
margin: 16px 0;
}

.add-file-message p {
color: green;
font-weight: bold;
font-size: 1.25rem;
letter-spacing: 2px;
}

.files-view-page-delete-btn {
margin: 0 auto !important;
} }

+ 11
- 10
src/components/Docs/DocsFilters.js Wyświetl plik

import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { import {
getFilesReq, getFilesReq,
updateFileFilterCat,
// updateFileFilterCat,
updateFileFilterExt, updateFileFilterExt,
updateFileFilterTag, updateFileFilterTag,
} from "../../store/actions/files/fileActions"; } from "../../store/actions/files/fileActions";


const DocsFilters = ({ open, handleClose, setPage }) => {
const DocsFilters = ({ open, handleClose, setPage, category }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { filters } = useSelector((s) => s.fileFilters); const { filters } = useSelector((s) => s.fileFilters);


dispatch(updateFileFilterExt(e.target.value)); dispatch(updateFileFilterExt(e.target.value));
const handleCheckboxesTags = (e) => const handleCheckboxesTags = (e) =>
dispatch(updateFileFilterTag(e.target.value)); dispatch(updateFileFilterTag(e.target.value));
const handleCheckboxesCat = (e) =>
dispatch(updateFileFilterCat(e.target.value));
// const handleCheckboxesCat = (e) =>
// dispatch(updateFileFilterCat(e.target.value));


const submitFiltersHandler = (e) => { const submitFiltersHandler = (e) => {
e.preventDefault(); e.preventDefault();


var catFilters = [];
filters.categories
?.filter((n) => n.isChecked)
.forEach((m) => catFilters.push(m.name));
var catFilters = [category && category];
// filters.categories
// ?.filter((n) => n.isChecked)
// .forEach((m) => catFilters.push(m.name));


var extFilters = []; var extFilters = [];
filters.extensions filters.extensions
))} ))}
</FormGroup> </FormGroup>
</div> </div>
<div
{/* <div
style={{ paddingTop: "10px" }} style={{ paddingTop: "10px" }}
className="custom-drawer-sub-card-label" className="custom-drawer-sub-card-label"
> >
/> />
))} ))}
</FormGroup> </FormGroup>
</div>
</div> */}
</div> </div>
<div className="custom-drawer-submit"> <div className="custom-drawer-submit">
<button <button
open: PropType.any, open: PropType.any,
handleClose: PropType.func, handleClose: PropType.func,
setPage: PropType.func, setPage: PropType.func,
category: PropType.string
}; };


export default DocsFilters; export default DocsFilters;

+ 25
- 3
src/pages/FilesPage/AddFile.js Wyświetl plik

import { FILES_VIEW_PAGE } from "../../constants/pages"; import { FILES_VIEW_PAGE } from "../../constants/pages";
import PropTypes from "prop-types"; import PropTypes from "prop-types";


const AddFile = ({history}) => {
const AddFile = ({ history }) => {
const [dropzoneActive, setDropzoneActive] = useState(false); const [dropzoneActive, setDropzoneActive] = useState(false);
const [pdfFile, setPdfFile] = useState(null); const [pdfFile, setPdfFile] = useState(null);
const [title, setTitle] = useState(""); const [title, setTitle] = useState("");
const [showMessage, setShowMessage] = useState(false);
const dispatch = useDispatch(); const dispatch = useDispatch();
const categories = useSelector(selectCategories); const categories = useSelector(selectCategories);
const tags = useSelector(selectTags); const tags = useSelector(selectTags);
const onSuccessUploadFile = () => { const onSuccessUploadFile = () => {
dispatch(resetIsCheckedTagsValue()); dispatch(resetIsCheckedTagsValue());
setPdfFile(null); setPdfFile(null);
setTitle("")
setTitle("");
setShowMessage(true);
}; };


useEffect(() => {
if (showMessage === true) {
setTimeout(() => {
setShowMessage(false);
}, 1000);
}
}, [showMessage]);

const handleDrop = (e) => { const handleDrop = (e) => {
e.preventDefault(); e.preventDefault();
const selectedFile = e.dataTransfer.files[0]; const selectedFile = e.dataTransfer.files[0];


return ( return (
<div className="files-page"> <div className="files-page">
<div className="l-t-rectangle"></div>
<div className="r-b-rectangle"></div>
<div className="files-page-card"> <div className="files-page-card">
<div className="files-page-card-title"> <div className="files-page-card-title">
<h1>Title</h1> <h1>Title</h1>
</div> </div>
</div> </div>


<div
className="add-file-message"
style={showMessage === false ? { display: "none" } : { display: "flex" }}
>
<p>Uspesno dodat fajl</p>
</div>

<div className="files-page-card"> <div className="files-page-card">
<div className="files-page-card-add-button" style={{alignItems:'center'}}>
<div
className="files-page-card-add-button"
style={{ alignItems: "center" }}
>
<p <p
className="applicant-ads-back-button" className="applicant-ads-back-button"
onClick={() => history.push(FILES_VIEW_PAGE)} onClick={() => history.push(FILES_VIEW_PAGE)}

+ 57
- 13
src/pages/FilesPage/FilesPage.js Wyświetl plik

import React, { useEffect } from 'react'
import React, { useEffect } from "react";
import PropTypes from "prop-types";
import { useSelector, useDispatch } from "react-redux";
import IconButton from "../../components/IconButton/IconButton";
import { setCategoriesReq } from "../../store/actions/categories/categoriesAction"; import { setCategoriesReq } from "../../store/actions/categories/categoriesAction";
import { selectCategories } from "../../store/selectors/categoriesSelector"; import { selectCategories } from "../../store/selectors/categoriesSelector";
import { useDispatch, useSelector } from 'react-redux';
import table from "../../assets/images/table.png";
import { FILES_VIEW_PAGE } from "../../constants/pages";


const FilesPage = () => {
const dispatch = useDispatch()
const FilesPage = ({ history }) => {
const categories = useSelector(selectCategories); const categories = useSelector(selectCategories);
const dispatch = useDispatch();

useEffect(() => { useEffect(() => {
dispatch(setCategoriesReq()); dispatch(setCategoriesReq());
})
}, []);

return ( return (
<div>
{categories.map((category,index) => (
<p key={index}>{category.name}</p>
)) }
</div>
)
}
<>
<div className="l-t-rectangle"></div>
<div className="r-b-rectangle"></div>
<div className="pl-144" style={{ paddingTop: "36px" }}>
<div style={{ marginBottom: "39px" }}>
<h1 className="page-heading">Kategorije</h1>
</div>
<div className="files-page-categories">
{categories &&
categories.map((category) => (
<div className="files-page-categories-category" key={category.id}>
<IconButton
className="c-btn c-btn--primary-outlined files-page-category-button"
data-testid="pattern-details-send-email"
onClick={() =>
history.push(FILES_VIEW_PAGE, { category: category.name })
}
>
<img
style={{
marginRight: "5px",
width: "12px",
height: "12px",
}}
src={table}
/>
{category.name}
</IconButton>
</div>
))}
</div>
</div>
</>
);
};

FilesPage.propTypes = {
history: PropTypes.shape({
replace: PropTypes.func,
push: PropTypes.func,
location: PropTypes.shape({
pathname: PropTypes.string,
}),
}),
};


export default FilesPage
export default FilesPage;

+ 40
- 15
src/pages/FilesPage/FilesViewPage.js Wyświetl plik

import DocsFilters from "../../components/Docs/DocsFilters"; import DocsFilters from "../../components/Docs/DocsFilters";
import { FETCH_FILES_LOADING } from "../../store/actions/files/fileActionConstants"; import { FETCH_FILES_LOADING } from "../../store/actions/files/fileActionConstants";
import { import {
deleteFileReq,
getFileFiltersReq, getFileFiltersReq,
getFilesReq, getFilesReq,
} from "../../store/actions/files/fileActions"; } from "../../store/actions/files/fileActions";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import searchImage from "../../assets/images/search.png"; import searchImage from "../../assets/images/search.png";
import IconButton from "../../components/IconButton/IconButton"; import IconButton from "../../components/IconButton/IconButton";
import { ADD_FILE } from "../../constants/pages";
import { ADD_FILE, FILES_PAGE } from "../../constants/pages";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { useLocation } from "react-router";
import deleteIcon from "../../assets/images/delete.png";


const FilesViewPage = ({history}) => {
const FilesViewPage = ({ history }) => {
const [toggleFiltersDrawer, setToggleFiltersDrawer] = useState(false); const [toggleFiltersDrawer, setToggleFiltersDrawer] = useState(false);
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const { filters } = useSelector((s) => s.fileFilters); const { filters } = useSelector((s) => s.fileFilters);
const { data } = useSelector((s) => s.files); const { data } = useSelector((s) => s.files);
const { t } = useTranslation(); const { t } = useTranslation();
const [isSearchFieldVisible, setIsSearchFieldVisible] = useState(false); const [isSearchFieldVisible, setIsSearchFieldVisible] = useState(false);
const { state } = useLocation();
// const [timer, setTimer] = useState(null); // const [timer, setTimer] = useState(null);


const dispatch = useDispatch(); const dispatch = useDispatch();


if (state === undefined) {
history.replace(FILES_PAGE);
}

const handleToggleFiltersDrawer = () => { const handleToggleFiltersDrawer = () => {
setToggleFiltersDrawer((oldState) => !oldState); setToggleFiltersDrawer((oldState) => !oldState);
}; };
payload: { payload: {
pageSize: 6, pageSize: 6,
currentPage: page, currentPage: page,
categories: [],
categories: [state && state.category],
extensions: [], extensions: [],
tags: [], tags: [],
content: "", content: "",
}, []); }, []);


const handleChange = (_, value) => { const handleChange = (_, value) => {
var catFilters = [];
filters.categories
?.filter((n) => n.isChecked)
.forEach((m) => catFilters.push(m.name));
var catFilters = [state && state.category];
// filters.categories
// ?.filter((n) => n.isChecked)
// .forEach((m) => catFilters.push(m.name));


var extFilters = []; var extFilters = [];
filters.extensions filters.extensions
dispatch(setContent(value)); dispatch(setContent(value));
}; };


const deleteFileHandler = (stream_id) => {
dispatch(deleteFileReq({ id: stream_id }));
};

const handleKeyDown = (event) => { const handleKeyDown = (event) => {
console.log(filters.content);
if (event.key === "Enter" && filters.content !== "") { if (event.key === "Enter" && filters.content !== "") {
var catFilters = [];
filters.categories
?.filter((n) => n.isChecked)
.forEach((m) => catFilters.push(m.name));
var catFilters = [state && state.category];


var extFilters = []; var extFilters = [];
filters.extensions filters.extensions
open={toggleFiltersDrawer} open={toggleFiltersDrawer}
handleClose={handleToggleFiltersDrawer} handleClose={handleToggleFiltersDrawer}
setPage={setPage} setPage={setPage}
category={state && state.category}
/> />
<div <div
// onClick={() => setIsSearchFieldVisible(false)}
className="pl-144 flex-center" className="pl-144 flex-center"
style={{ style={{
paddingTop: "36px", paddingTop: "36px",
</Fade> </Fade>
</div> </div>
<div className="flex-center"> <div className="flex-center">
{/* <button></button> */}
<IconButton <IconButton
className="c-btn c-btn--primary-outlined candidate-btn search-field userPageBtn ml-20px no-padding custom-filter-button" className="c-btn c-btn--primary-outlined candidate-btn search-field userPageBtn ml-20px no-padding custom-filter-button"
onClick={handleChangeVisibility} onClick={handleChangeVisibility}
</div> </div>
<div <div
className="pl-144" className="pl-144"
// onClick={() => setIsSearchFieldVisible(false)}
style={{ style={{
display: "flex", display: "flex",
marginTop: "39px", marginTop: "39px",
{/* Document size (MB) */} {/* Document size (MB) */}
Veličina dokumenta Veličina dokumenta
</th> </th>
<th>
{/* {t("users.position")} */}
{/* Document size (MB) */}
Obriši dokument
</th>
{/* <th> */} {/* <th> */}
{/* {t("users.position")} */} {/* {t("users.position")} */}
{/* Document size (MB) */} {/* Document size (MB) */}
<td className="docs-name">{n.title}</td> <td className="docs-name">{n.title}</td>
<td>{n.file_type && n.file_type}</td> <td>{n.file_type && n.file_type}</td>
<td className="profession">{n.cached_file_size}kB</td> <td className="profession">{n.cached_file_size}kB</td>
<td className="profession">
<IconButton
className="c-btn c-btn--primary-outlined files-view-page-delete-btn"
onClick={() => deleteFileHandler(n.stream_id)}
>
<img
style={{
width: "12px",
height: "12px",
}}
src={deleteIcon}
/>
</IconButton>
</td>
</tr> </tr>
))} ))}
</tbody> </tbody>

+ 1
- 0
src/request/apiEndpoints.js Wyświetl plik

files: { files: {
uploadFile: base + "/files", uploadFile: base + "/files",
all: base + "/files/filtered", all: base + "/files/filtered",
deleteFile: base + "/files/delete-file",
}, },
}; };

+ 3
- 1
src/request/filesRequest.js Wyświetl plik

import { postRequest } from ".";
import { deleteRequest, postRequest } from ".";
import apiEndpoints from "./apiEndpoints"; import apiEndpoints from "./apiEndpoints";


export const uploadFileRequest = (payload) => export const uploadFileRequest = (payload) =>
postRequest(apiEndpoints.files.uploadFile, payload); postRequest(apiEndpoints.files.uploadFile, payload);
export const deleteFileRequest = (id) =>
deleteRequest(apiEndpoints.files.deleteFile + "/" + id);

+ 5
- 0
src/store/actions/files/fileActionConstants.js Wyświetl plik

export const FETCH_FILES_ERR = createErrorType(FETCH_FILES_SCOPE); export const FETCH_FILES_ERR = createErrorType(FETCH_FILES_SCOPE);
export const FETCH_FILES_SUCCESS = createSuccessType(FETCH_FILES_SCOPE); export const FETCH_FILES_SUCCESS = createSuccessType(FETCH_FILES_SCOPE);
export const FETCH_FILES_LOADING = createLoadingType(FETCH_FILES_SCOPE); export const FETCH_FILES_LOADING = createLoadingType(FETCH_FILES_SCOPE);

const DELETE_FILE_SCOPE = "DELETE_FILE"
export const DELETE_FILE_REQ = createFetchType(DELETE_FILE_SCOPE)
export const DELETE_FILE_ERR = createErrorType(DELETE_FILE_SCOPE)
export const DELETE_FILE_SUCCESS = createSuccessType(DELETE_FILE_SCOPE)

+ 20
- 2
src/store/actions/files/fileActions.js Wyświetl plik

UPDATE_FILTERS_CATEGORY, UPDATE_FILTERS_CATEGORY,
UPDATE_FILTERS_EXTENSION, UPDATE_FILTERS_EXTENSION,
UPDATE_FILTERS_TAG, UPDATE_FILTERS_TAG,
SET_CONTENT
SET_CONTENT,
DELETE_FILE_REQ,
DELETE_FILE_ERR,
DELETE_FILE_SUCCESS
} from "./fileActionConstants"; } from "./fileActionConstants";


export const getFileFiltersReq = () => ({ export const getFileFiltersReq = () => ({
export const setContent = (payload) => ({ export const setContent = (payload) => ({
type:SET_CONTENT, type:SET_CONTENT,
payload payload
})
})

export const deleteFileReq = (payload) => ({
type: DELETE_FILE_REQ,
payload
});

export const deleteFileError = (payload) => ({
type: DELETE_FILE_ERR,
payload,
});

export const deleteFileAction = (payload) => ({
type: DELETE_FILE_SUCCESS,
payload
});

+ 18
- 0
src/store/reducers/files/getFilesReducer.js Wyświetl plik

FETCH_FILES_ERR, FETCH_FILES_ERR,
FETCH_FILES_SUCCESS, FETCH_FILES_SUCCESS,
} from "../../actions/files/fileActionConstants"; } from "../../actions/files/fileActionConstants";
import {
DELETE_FILE_ERR,
DELETE_FILE_SUCCESS,
} from "../../actions/files/fileActionConstants";


const initialState = { const initialState = {
data: {}, data: {},
{ {
[FETCH_FILES_SUCCESS]: setFiles, [FETCH_FILES_SUCCESS]: setFiles,
[FETCH_FILES_ERR]: setFilesErrorMessage, [FETCH_FILES_ERR]: setFilesErrorMessage,
[DELETE_FILE_SUCCESS]: deleteFileReducer,
[DELETE_FILE_ERR]: deleteFileReducerError,
}, },
initialState initialState
); );
fetchFilesErrorMessage: action.payload, fetchFilesErrorMessage: action.payload,
}; };
} }

function deleteFileReducer(state, action) {
const newArr = state.data.data.filter(x => x.stream_id !== action.payload)
return { ...state, data: {...state.data, data: newArr} };
}

function deleteFileReducerError(state, action) {
return {
...state,
fetchFilesErrorMessage: action.payload,
};
}

+ 1
- 1
src/store/reducers/index.js Wyświetl plik

categories: categoriesReducer, categories: categoriesReducer,
tags: tagsReducer, tags: tagsReducer,
fileFilters: fileFiltersReducer, fileFilters: fileFiltersReducer,
files: getFilesReducer
files: getFilesReducer,
}); });

+ 19
- 3
src/store/saga/filesSaga.js Wyświetl plik

import { addHeaderToken } from "../../request"; import { addHeaderToken } from "../../request";
import { rejectErrorCodeHelper } from "../../util/helpers/rejectErrorCodeHelper"; import { rejectErrorCodeHelper } from "../../util/helpers/rejectErrorCodeHelper";
import { UPLOAD_FILE_REQ } from "../actions/uploadFile/uploadFileActionConstants"; import { UPLOAD_FILE_REQ } from "../actions/uploadFile/uploadFileActionConstants";
import { uploadFileRequest } from "../../request/filesRequest";
import { deleteFileRequest, uploadFileRequest } from "../../request/filesRequest";
import { getAllFilesReq } from "../../request/fileRequests"; import { getAllFilesReq } from "../../request/fileRequests";
import { FETCH_FILES_REQ } from "../actions/files/fileActionConstants";
import { getFileError, getFileSuccess } from "../actions/files/fileActions";
import { DELETE_FILE_REQ, FETCH_FILES_REQ } from "../actions/files/fileActionConstants";
import { deleteFileAction, deleteFileError, getFileError, getFileSuccess } from "../actions/files/fileActions";


export function* uploadFileSaga({ payload }) { export function* uploadFileSaga({ payload }) {
try { try {
} }
} }
} }

export function* deleteFileSaga({ payload }) {
try {
const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN);
yield call(addHeaderToken, JwtToken);
yield call(deleteFileRequest, payload.id);
yield put(deleteFileAction(payload.id))
} catch (error) {
if (error.response && error.response.data) {
const errorMessage = yield call(rejectErrorCodeHelper, error);
yield put(deleteFileError(errorMessage));
}
}
}

export default function* filesSaga() { export default function* filesSaga() {
yield all([takeLatest(UPLOAD_FILE_REQ, uploadFileSaga)]); yield all([takeLatest(UPLOAD_FILE_REQ, uploadFileSaga)]);
yield all([takeEvery(FETCH_FILES_REQ, getAll)]); yield all([takeEvery(FETCH_FILES_REQ, getAll)]);
yield all([takeLatest(DELETE_FILE_REQ, deleteFileSaga)]);
} }

Ładowanie…
Anuluj
Zapisz