#6 Upload pdf files

Слито
bronjaermin слито 1 коммит(ов) из feature/upload_pdf_fe в FE_dev 3 лет назад
  1. 0
    1
      src/components/Ads/ApplyForAdFourthStage.js
  2. 0
    2
      src/components/Patterns/PatternFilters.js
  3. 59
    51
      src/pages/FilesPage/FilesPage.js
  4. 7
    0
      src/request/apiEndpoints.js
  5. 5
    0
      src/request/categoriesRequest.js
  6. 5
    0
      src/request/filesRequest.js
  7. 2
    0
      src/request/tagsRequest.js
  8. 19
    0
      src/store/actions/categories/categoriesAction.js
  9. 11
    0
      src/store/actions/categories/categoriesActionConstants.js
  10. 30
    0
      src/store/actions/tags/tagsAction.js
  11. 14
    0
      src/store/actions/tags/tagsActionConstants.js
  12. 12
    0
      src/store/actions/uploadFile/uploadFileActionConstants.js
  13. 20
    0
      src/store/actions/uploadFile/uploadFileActions.js
  14. 32
    0
      src/store/reducers/category/categoriesReducer.js
  15. 32
    0
      src/store/reducers/file/uploadFileReducer.js
  16. 7
    1
      src/store/reducers/index.js
  17. 60
    0
      src/store/reducers/tag/tagsReducer.js
  18. 26
    0
      src/store/saga/categoriesSaga.js
  19. 28
    3
      src/store/saga/filesSaga.js
  20. 3
    1
      src/store/saga/index.js
  21. 20
    3
      src/store/saga/tagsSaga.js
  22. 13
    0
      src/store/selectors/categoriesSelector.js
  23. 10
    0
      src/store/selectors/tagsSelector.js

+ 0
- 1
src/components/Ads/ApplyForAdFourthStage.js Просмотреть файл

@@ -69,7 +69,6 @@ const ApplyForAdFourthStage = ({
value={pdfFile}
data-testid="apply-for-ad-modal-fourth-stage-pdf-input"
onChange={(e) => {
console.log("Ovde smo");
setPdfFile(e.target.files[0]);
}}
/>

+ 0
- 2
src/components/Patterns/PatternFilters.js Просмотреть файл

@@ -17,8 +17,6 @@ const PatternFilters = ({
const dispatch = useDispatch();
const { t } = useTranslation();

console.log("OVDE", selectionLevelFilter);

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


+ 59
- 51
src/pages/FilesPage/FilesPage.js Просмотреть файл

@@ -3,65 +3,69 @@ import { Checkbox, FormControlLabel, MenuItem, Select } from "@mui/material";
import { useTranslation } from "react-i18next";
import uploadIcon from "../../assets/images/upload.png";
import IconButton from "../../components/IconButton/IconButton";
import { useSelector, useDispatch } from "react-redux";
import { selectCategories } from "../../store/selectors/categoriesSelector";
import { useEffect } from "react";
import { setCategoriesReq } from "../../store/actions/categories/categoriesAction";
import {
changeTagIsCheckedValue,
resetIsCheckedTagsValue,
setTagsReq,
} from "../../store/actions/tags/tagsAction";
import { selectTags } from "../../store/selectors/tagsSelector";
import { uploadFileReq } from "../../store/actions/uploadFile/uploadFileActions";

const FilesPage = () => {
const [dropzoneActive, setDropzoneActive] = useState(false);
const [pdfFile, setPdfFile] = useState(null);
const [categories, setCategories] = useState([
{ id: 1, value: "a" },
{ id: 2, value: "b" },
{ id: 3, value: "c" },
{ id: 4, value: "d" },
{ id: 5, value: "e" },
{ id: 6, value: "f" },
{ id: 7, value: "g" },
{ id: 8, value: "h" },
]);
const [tags, setTags] = useState([
{ id: 1, value: "a", isChecked: false },
{ id: 2, value: "a", isChecked: false },
{ id: 3, value: "a", isChecked: false },
{ id: 4, value: "a", isChecked: false },
{ id: 5, value: "a", isChecked: false },
{ id: 6, value: "a", isChecked: false },
{ id: 7, value: "a", isChecked: false },
{ id: 8, value: "a", isChecked: false },
]);
const dispatch = useDispatch();
const categories = useSelector(selectCategories);
const tags = useSelector(selectTags);
const [selectedCategory, setSelectedCategory] = useState(null);
const { t } = useTranslation();

console.log(selectedCategory);
useEffect(() => {
dispatch(setCategoriesReq());
dispatch(setTagsReq());
}, []);

const onSuccessUploadFile = () => {
dispatch(resetIsCheckedTagsValue())
setPdfFile(null)
}

const handleDrop = (e) => {
e.preventDefault();
const selectedFile = e.dataTransfer.files[0];
const fileName = selectedFile.name;
const fileExtension = selectedFile.name.split(".").pop();
const fileSize = selectedFile.size;
console.log(fileName, fileExtension, fileSize);
setPdfFile(selectedFile);
};

const handleChangeInputFile = (e) => {
const selectedFile = e.target.files[0];
const fileName = selectedFile.name;
const fileExtension = selectedFile.name.split(".").pop();
const fileSize = selectedFile.size;
console.log(fileName, fileExtension, fileSize);
setPdfFile(selectedFile);
};

const selectCategoryHandler = (e) => {
setSelectedCategory(e.target.value);
setCategories((oldState) => [...oldState]);
};

const onChangeTagsCheckbox = (id) => {
const newArr = tags.map((x) =>
x.id === id ? { ...x, isChecked: !x.isChecked } : x
);
dispatch(changeTagIsCheckedValue(id));
};

const uploadFileHandler = () => {
const tagsIds = tags
.filter((tag) => tag.isChecked === true)
.map((tag) => Number(tag.id));

setTags(newArr);
dispatch(
uploadFileReq({
categoryId: selectedCategory,
tagsIds,
fileToUpload: pdfFile,
onSuccessUploadFile
})
);
};

return (
@@ -83,9 +87,9 @@ const FilesPage = () => {
<MenuItem
key={index}
sx={{ textAlign: "left" }}
value={category.value}
value={category.id}
>
{category.value}
{category.name}
</MenuItem>
))}
</Select>
@@ -98,20 +102,21 @@ const FilesPage = () => {
</div>
<div className="files-page-card-content">
<div className="files-page-card-content-checkboxes">
{tags.map((x) => (
<FormControlLabel
key={x.id}
control={
<Checkbox
value={x.value}
checked={x.isChecked}
onChange={onChangeTagsCheckbox.bind(this, x.id)}
className="create-ad-second-step-checkbox"
/>
}
label={x.value}
/>
))}
{tags &&
tags.map((tag) => (
<FormControlLabel
key={tag.id}
control={
<Checkbox
value={tag.name}
checked={tag.isChecked}
onChange={onChangeTagsCheckbox.bind(this, tag.id)}
className="create-ad-second-step-checkbox"
/>
}
label={tag.name}
/>
))}
</div>
</div>
</div>
@@ -177,7 +182,10 @@ const FilesPage = () => {

<div className="files-page-card">
<div className="files-page-card-add-button">
<IconButton className="c-btn ads-page-btn c-btn--primary add-ad-btn">
<IconButton
className="c-btn ads-page-btn c-btn--primary add-ad-btn"
onClick={uploadFileHandler}
>
+ {t("files.addFile")}
</IconButton>
</div>

+ 7
- 0
src/request/apiEndpoints.js Просмотреть файл

@@ -69,10 +69,17 @@ export default {
allTests: base + "/screeningtest",
createTest: base + "/screeningtest",
},
categories: {
allCategories: base + "/categories/names",
},
tags: {
allTags: base + "/tags/names",
},
fileTags: {
filters: base + "/tags",
},
files:{
uploadFile: base + "/files",
all: base + "/files"
}
};

+ 5
- 0
src/request/categoriesRequest.js Просмотреть файл

@@ -0,0 +1,5 @@
import { getRequest } from ".";
import apiEndpoints from "./apiEndpoints";

export const getAllCategories = () =>
getRequest(apiEndpoints.categories.allCategories);

+ 5
- 0
src/request/filesRequest.js Просмотреть файл

@@ -0,0 +1,5 @@
import { postRequest } from ".";
import apiEndpoints from "./apiEndpoints";

export const uploadFileRequest = (payload) =>
postRequest(apiEndpoints.files.uploadFile, payload);

+ 2
- 0
src/request/tagsRequest.js Просмотреть файл

@@ -2,3 +2,5 @@ import { getRequest } from ".";
import apiEndpoints from "./apiEndpoints";

export const getFileFilters = () => getRequest(apiEndpoints.fileTags.filters);
export const getAllTags = () =>
getRequest(apiEndpoints.tags.allTags);

+ 19
- 0
src/store/actions/categories/categoriesAction.js Просмотреть файл

@@ -0,0 +1,19 @@
import {
FETCH_CATEGORIES_REQ,
FETCH_CATEGORIES_SUCCESS,
FETCH_CATEGORIES_ERR,
} from "./categoriesActionConstants";

export const setCategoriesReq = () => ({
type: FETCH_CATEGORIES_REQ,
});

export const setCategoriesError = (payload) => ({
type: FETCH_CATEGORIES_ERR,
payload,
});

export const setCategories = (payload) => ({
type: FETCH_CATEGORIES_SUCCESS,
payload,
});

+ 11
- 0
src/store/actions/categories/categoriesActionConstants.js Просмотреть файл

@@ -0,0 +1,11 @@
import {
createFetchType,
createSuccessType,
createErrorType,
} from "../actionHelpers";

const FETCH_CATEGORIES_SCOPE = "FETCH_CATEGORIES";

export const FETCH_CATEGORIES_REQ = createFetchType(FETCH_CATEGORIES_SCOPE);
export const FETCH_CATEGORIES_ERR = createErrorType(FETCH_CATEGORIES_SCOPE);
export const FETCH_CATEGORIES_SUCCESS = createSuccessType(FETCH_CATEGORIES_SCOPE);

+ 30
- 0
src/store/actions/tags/tagsAction.js Просмотреть файл

@@ -0,0 +1,30 @@
import {
FETCH_TAGS_REQ,
FETCH_TAGS_SUCCESS,
FETCH_TAGS_ERR,
CHANGE_TAG_ISCHECKED_VALUE,
RESET_CHECKED_TAGS,
} from "./tagsActionConstants";

export const setTagsReq = () => ({
type: FETCH_TAGS_REQ,
});

export const setTagsError = (payload) => ({
type: FETCH_TAGS_ERR,
payload,
});

export const setTags = (payload) => ({
type: FETCH_TAGS_SUCCESS,
payload,
});

export const changeTagIsCheckedValue = (payload) => ({
type: CHANGE_TAG_ISCHECKED_VALUE,
payload,
});

export const resetIsCheckedTagsValue = () => ({
type: RESET_CHECKED_TAGS,
});

+ 14
- 0
src/store/actions/tags/tagsActionConstants.js Просмотреть файл

@@ -0,0 +1,14 @@
import {
createFetchType,
createSuccessType,
createErrorType,
} from "../actionHelpers";

const FETCH_TAGS_SCOPE = "FETCH_TAGS";

export const FETCH_TAGS_REQ = createFetchType(FETCH_TAGS_SCOPE);
export const FETCH_TAGS_ERR = createErrorType(FETCH_TAGS_SCOPE);
export const FETCH_TAGS_SUCCESS = createSuccessType(FETCH_TAGS_SCOPE);

export const CHANGE_TAG_ISCHECKED_VALUE = "CHANGE_TAG_ISCHECKED_VALUE";
export const RESET_CHECKED_TAGS = "RESET_CHECKED_TAGS";

+ 12
- 0
src/store/actions/uploadFile/uploadFileActionConstants.js Просмотреть файл

@@ -0,0 +1,12 @@
import {
createFetchType,
createSuccessType,
createErrorType,
} from "../actionHelpers";
const UPLOAD_FILE_SCOPE = "UPLOAD_FILE";
export const UPLOAD_FILE_REQ = createFetchType(UPLOAD_FILE_SCOPE);
export const UPLOAD_FILE_ERR = createErrorType(UPLOAD_FILE_SCOPE);
export const UPLOAD_FILE_SUCCESS = createSuccessType(UPLOAD_FILE_SCOPE);

+ 20
- 0
src/store/actions/uploadFile/uploadFileActions.js Просмотреть файл

@@ -0,0 +1,20 @@
import {
UPLOAD_FILE_REQ,
UPLOAD_FILE_SUCCESS,
UPLOAD_FILE_ERR,
} from "./uploadFileActionConstants";

export const uploadFileReq = (payload) => ({
type: UPLOAD_FILE_REQ,
payload,
});

export const uploadFileError = (payload) => ({
type: UPLOAD_FILE_ERR,
payload,
});

export const uploadFile = (payload) => ({
type: UPLOAD_FILE_SUCCESS,
payload,
});

+ 32
- 0
src/store/reducers/category/categoriesReducer.js Просмотреть файл

@@ -0,0 +1,32 @@
import {
FETCH_CATEGORIES_ERR,
FETCH_CATEGORIES_SUCCESS,
} from "../../actions/categories/categoriesActionConstants";
import createReducer from "../../utils/createReducer";

const initialState = {
categories: [],
errorMessage: "",
};

export default createReducer(
{
[FETCH_CATEGORIES_SUCCESS]: setStateCategories,
[FETCH_CATEGORIES_ERR]: setCategoriesErrorMessage,
},
initialState
);

function setStateCategories(state, action) {
return {
...state,
categories: action.payload,
};
}
function setCategoriesErrorMessage(state, action) {
return {
...state,
errorMessage: action.payload,
};
}

+ 32
- 0
src/store/reducers/file/uploadFileReducer.js Просмотреть файл

@@ -0,0 +1,32 @@
import {
UPLOAD_FILE_SUCCESS,
UPLOAD_FILE_ERR,
} from "../../actions/uploadFile/uploadFileActionConstants";
import createReducer from "../../utils/createReducer";

const initialState = {
file: null,
errorMessage: "",
};

export default createReducer(
{
[UPLOAD_FILE_SUCCESS]: setStateFile,
[UPLOAD_FILE_ERR]: setFileErrorMessage,
},
initialState
);

function setStateFile(state, action) {
return {
...state,
file: action.payload,
};
}

function setFileErrorMessage(state, action) {
return {
...state,
errorMessage: action.payload,
};
}

+ 7
- 1
src/store/reducers/index.js Просмотреть файл

@@ -33,6 +33,9 @@ import applyForAdReducer from "./applicants/applyForAdReducer";
import statusUpdateReducer from "./processes/statusUpdateReducer";
import interviewerUpdateReducer from "./processes/interviewerUpdateReducer";
import screeningTestsReducer from "./screeningTests/screeningTestsReducer";
import uploadFileReducer from "./file/uploadFileReducer";
import categoriesReducer from "./category/categoriesReducer";
import tagsReducer from "./tag/tagsReducer";
import fileFiltersReducer from "./files/fileFiltersReducer";
import getFilesReducer from "./files/getFilesReducer";

@@ -70,7 +73,10 @@ export default combineReducers({
applyForAd: applyForAdReducer,
statusUpdate: statusUpdateReducer,
interviewerUpdate: interviewerUpdateReducer,
screeningTests:screeningTestsReducer,
screeningTests: screeningTestsReducer,
uploadFile: uploadFileReducer,
categories: categoriesReducer,
tags: tagsReducer,
fileFilters: fileFiltersReducer,
files: getFilesReducer
});

+ 60
- 0
src/store/reducers/tag/tagsReducer.js Просмотреть файл

@@ -0,0 +1,60 @@
import {
FETCH_TAGS_ERR,
FETCH_TAGS_SUCCESS,
CHANGE_TAG_ISCHECKED_VALUE,
RESET_CHECKED_TAGS,
} from "../../actions/tags/tagsActionConstants";
import createReducer from "../../utils/createReducer";

const initialState = {
tags: [],
errorMessage: "",
};

export default createReducer(
{
[FETCH_TAGS_SUCCESS]: setStateTags,
[FETCH_TAGS_ERR]: setTagsErrorMessage,
[CHANGE_TAG_ISCHECKED_VALUE]: setIsCheckedTags,
[RESET_CHECKED_TAGS]: resetIsCheckedTags,
},
initialState
);

function setStateTags(state, action) {
return {
...state,
tags: action.payload,
};
}

function setTagsErrorMessage(state, action) {
return {
...state,
errorMessage: action.payload,
};
}

function setIsCheckedTags(state, action) {
const tmpIndex = state.tags.findIndex(
(x) => x.id === action.payload
);

if (tmpIndex === -1) {
return state;
}

return {
...state,
tags: state.tags.map((tag, index) =>
tmpIndex === index ? { ...tag, isChecked: !tag.isChecked } : tag
),
};
}

function resetIsCheckedTags(state) {
return {
...state,
tags: state.tags.map((tag) => ({ ...tag, isChecked: false })),
};
}

+ 26
- 0
src/store/saga/categoriesSaga.js Просмотреть файл

@@ -0,0 +1,26 @@
import { all, call, put, takeLatest } from "redux-saga/effects";
import { setCategories, setCategoriesError } from "../actions/categories/categoriesAction";
import { authScopeStringGetHelper } from "../../util/helpers/authScopeHelpers";
import { JWT_TOKEN } from "../../constants/localStorage";
import { addHeaderToken } from "../../request";
import { rejectErrorCodeHelper } from "../../util/helpers/rejectErrorCodeHelper";
import { FETCH_CATEGORIES_REQ } from "../actions/categories/categoriesActionConstants";
import { getAllCategories } from "../../request/categoriesRequest";

export function* getCategories() {
try {
const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN);
yield call(addHeaderToken, JwtToken);
const result = yield call(getAllCategories);
yield put(setCategories(result.data));
} catch (error) {
const errorMessage = yield call(rejectErrorCodeHelper, error);
yield put(setCategoriesError(errorMessage));
}
}

export default function* categoriesSaga() {
yield all([
takeLatest(FETCH_CATEGORIES_REQ, getCategories),
]);
}

+ 28
- 3
src/store/saga/filesSaga.js Просмотреть файл

@@ -1,15 +1,39 @@
import { all, call, put, takeEvery } from "redux-saga/effects";
import { all, call, put, takeLatest, takeEvery } from "redux-saga/effects";
import {
uploadFile,
uploadFileError,
} from "../actions/uploadFile/uploadFileActions";
import { authScopeStringGetHelper } from "../../util/helpers/authScopeHelpers";
import { JWT_TOKEN } from "../../constants/localStorage";
import { addHeaderToken } from "../../request";
import { getAllFilesReq } from "../../request/fileRequests";
import { authScopeStringGetHelper } from "../../util/helpers/authScopeHelpers";
import { rejectErrorCodeHelper } from "../../util/helpers/rejectErrorCodeHelper";
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";

export function* uploadFileSaga({ payload }) {
try {
const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN);
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]);
formData.append("fileToUpload", payload.fileToUpload);
const result = yield call(uploadFileRequest, formData);
yield put(uploadFile(result.data));
payload.onSuccessUploadFile();
} catch (error) {
const errorMessage = yield call(rejectErrorCodeHelper, error);
yield put(uploadFileError(errorMessage));
}
}

export function* getAll() {
try {
const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN);
@@ -24,5 +48,6 @@ export function* getAll() {
}
}
export default function* filesSaga() {
yield all([takeLatest(UPLOAD_FILE_REQ, uploadFileSaga)]);
yield all([takeEvery(FETCH_FILES_REQ, getAll)]);
}

+ 3
- 1
src/store/saga/index.js Просмотреть файл

@@ -11,6 +11,7 @@ import scheduleSaga from "./scheduleSaga";
import registerSaga from "./registerSaga";
import applicantsSaga from "./applicantsSaga";
import screeningTestsSaga from "./screeningTestsSaga";
import categoriesSaga from "./categoriesSaga";
import tagsSaga from "./tagsSaga";
import filesSaga from "./filesSaga";

@@ -28,7 +29,8 @@ export default function* rootSaga() {
registerSaga(),
applicantsSaga(),
screeningTestsSaga(),
filesSaga(),
categoriesSaga(),
tagsSaga(),
filesSaga()
]);
}

+ 20
- 3
src/store/saga/tagsSaga.js Просмотреть файл

@@ -1,15 +1,31 @@
import { all, call, put, takeEvery } from "redux-saga/effects";
import { all, call, put, takeLatest, takeEvery } from "redux-saga/effects";
import { setTags, setTagsError } from "../actions/tags/tagsAction";
import { authScopeStringGetHelper } from "../../util/helpers/authScopeHelpers";
import { JWT_TOKEN } from "../../constants/localStorage";
import { addHeaderToken } from "../../request";
import { getFileFilters } from "../../request/tagsRequest";
import { authScopeStringGetHelper } from "../../util/helpers/authScopeHelpers";
import { rejectErrorCodeHelper } from "../../util/helpers/rejectErrorCodeHelper";
import { FETCH_TAGS_REQ } from "../actions/tags/tagsActionConstants";
import { getAllTags } from "../../request/tagsRequest";
import { getFileFilters } from "../../request/tagsRequest";
import { FILE_FILTERS_REQ } from "../actions/files/fileActionConstants";
import {
getFileFiltersError,
getFileFiltersSuccess,
} from "../actions/files/fileActions";

export function* getTags() {
try {
const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN);
yield call(addHeaderToken, JwtToken);
const result = yield call(getAllTags);
const resultData = result.data.map((tag) => ({ ...tag, isChecked: false }));
yield put(setTags(resultData));
} catch (error) {
const errorMessage = yield call(rejectErrorCodeHelper, error);
yield put(setTagsError(errorMessage));
}
}

export function* getFileFiltersGen() {
try {
const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN);
@@ -24,5 +40,6 @@ export function* getFileFiltersGen() {
}
}
export default function* tagsSaga() {
yield all([takeLatest(FETCH_TAGS_REQ, getTags)]);
yield all([takeEvery(FILE_FILTERS_REQ, getFileFiltersGen)]);
}

+ 13
- 0
src/store/selectors/categoriesSelector.js Просмотреть файл

@@ -0,0 +1,13 @@
import { createSelector } from "@reduxjs/toolkit";

export const categoriesSelector = (state) => state.categories;

export const selectCategories = createSelector(
categoriesSelector,
(state) => state.categories
);

export const selectCategoriesError = createSelector(
categoriesSelector,
(state) => state.errorMessage
);

+ 10
- 0
src/store/selectors/tagsSelector.js Просмотреть файл

@@ -0,0 +1,10 @@
import { createSelector } from "@reduxjs/toolkit";

export const tagsSelector = (state) => state.tags;

export const selectTags = createSelector(tagsSelector, (state) => state.tags);

export const selectTagsError = createSelector(
tagsSelector,
(state) => state.errorMessage
);

Загрузка…
Отмена
Сохранить