| .files-button-responsive { | .files-button-responsive { | ||||
| gap: 5px; | gap: 5px; | ||||
| width: 105px; | |||||
| width: 85px; | |||||
| height: 31px; | height: 31px; | ||||
| } | } | ||||
| .add-categories-files > button:first-child { | |||||
| margin-left: 0px !important; | |||||
| } | |||||
| .file-viewer-close-btn { | .file-viewer-close-btn { | ||||
| width: 100px; | width: 100px; | ||||
| align-self: flex-end; | align-self: flex-end; |
| import CloseIcon from "@mui/icons-material/Close"; | import CloseIcon from "@mui/icons-material/Close"; | ||||
| import LogoutIcon from "@mui/icons-material/Logout"; | import LogoutIcon from "@mui/icons-material/Logout"; | ||||
| import UserProfile from "../Profile/UserProfile"; | import UserProfile from "../Profile/UserProfile"; | ||||
| import { useSelector } from "react-redux"; | |||||
| import { useDispatch, useSelector } from "react-redux"; | |||||
| //import { userSelector } from "../../store/selectors/userSelectors"; | //import { userSelector } from "../../store/selectors/userSelectors"; | ||||
| import { Link, useLocation } from "react-router-dom"; | import { Link, useLocation } from "react-router-dom"; | ||||
| import rs from "../../assets/images/rs.png"; | import rs from "../../assets/images/rs.png"; | ||||
| import en from "../../assets/images/en.png"; | import en from "../../assets/images/en.png"; | ||||
| import { logoutUser } from "../../store/actions/login/loginActions"; | |||||
| const NavbarComponent = () => { | const NavbarComponent = () => { | ||||
| const navItems = [ | |||||
| "users", | |||||
| "files" | |||||
| ]; | |||||
| const navItems = ["users", "files"]; | |||||
| const { pathname } = useLocation(); | const { pathname } = useLocation(); | ||||
| const [openDrawer, setOpenDrawer] = useState(false); | const [openDrawer, setOpenDrawer] = useState(false); | ||||
| const [preview, setPreview] = useState(false); | const [preview, setPreview] = useState(false); | ||||
| const theme = useTheme(); | const theme = useTheme(); | ||||
| const matches = useMediaQuery(theme.breakpoints.down("sm")); | const matches = useMediaQuery(theme.breakpoints.down("sm")); | ||||
| const dispatch = useDispatch(); | |||||
| // const toggleColorMode = useContext(ColorModeContext); | // const toggleColorMode = useContext(ColorModeContext); | ||||
| const logout = () => { | |||||
| dispatch(logoutUser()); | |||||
| }; | |||||
| let userRef = useRef(); | let userRef = useRef(); | ||||
| let btnRef = useRef(); | let btnRef = useRef(); | ||||
| }; | }; | ||||
| const filterNavItems = () => { | const filterNavItems = () => { | ||||
| return navItems.filter(n => ((n === "users" && user.role === "SuperAdmin") || n !== "users")) | |||||
| } | |||||
| return navItems.filter( | |||||
| (n) => (n === "users" && user.role === "SuperAdmin") || n !== "users" | |||||
| ); | |||||
| }; | |||||
| useEffect(() => { | useEffect(() => { | ||||
| let handler = (e) => { | let handler = (e) => { | ||||
| {/* <Typography>s</Typography> */} | {/* <Typography>s</Typography> */} | ||||
| <div className="flex-center"> | <div className="flex-center"> | ||||
| <Button | <Button | ||||
| onClick={logout} | |||||
| sx={{ | sx={{ | ||||
| padding: "18px 72px", | padding: "18px 72px", | ||||
| border: "1px solid #226cb0", | border: "1px solid #226cb0", |
| addFileSuccessfullyAddedFile: "Successfully added file", | addFileSuccessfullyAddedFile: "Successfully added file", | ||||
| addFileGoBackToFiles: "Go back to all files", | addFileGoBackToFiles: "Go back to all files", | ||||
| createCategoryModalTitle: "Create category", | createCategoryModalTitle: "Create category", | ||||
| createTagModalTitle: "Create tag", | |||||
| createCategoryModalPlaceholder: "Category name", | createCategoryModalPlaceholder: "Category name", | ||||
| createTagModalPlaceholder: "Tag name", | |||||
| close: "Close", | close: "Close", | ||||
| createCategoryModalSubmitButton: "Create category", | createCategoryModalSubmitButton: "Create category", | ||||
| createTagModalSubmitButton: "Create tag", | |||||
| folders: "Folders", | folders: "Folders", | ||||
| file: "File", | file: "File", | ||||
| files: "Files", | files: "Files", | ||||
| documents: "| Documents", | documents: "| Documents", | ||||
| extension: "Extension", | extension: "Extension", | ||||
| tags: "Tags", | tags: "Tags", | ||||
| search: "Search" | |||||
| search: "Search", | |||||
| tag:"Tag" | |||||
| } | } | ||||
| }; | }; |
| addFileSuccessfullyAddedFile: "Uspešno dodat fajl", | addFileSuccessfullyAddedFile: "Uspešno dodat fajl", | ||||
| addFileGoBackToFiles: "Nazad na sve fajlove", | addFileGoBackToFiles: "Nazad na sve fajlove", | ||||
| createCategoryModalTitle: "Napravite kategoriju", | createCategoryModalTitle: "Napravite kategoriju", | ||||
| createTagModalTitle: "Napravite tag", | |||||
| createCategoryModalPlaceholder: "Naziv kategorije", | createCategoryModalPlaceholder: "Naziv kategorije", | ||||
| createTagModalPlaceholder: "Naziv taga", | |||||
| close: "Izađite", | close: "Izađite", | ||||
| createCategoryModalSubmitButton: "Napravite kategoriju", | createCategoryModalSubmitButton: "Napravite kategoriju", | ||||
| createTagModalSubmitButton: "Napravite tag", | |||||
| folders: "Folderi", | folders: "Folderi", | ||||
| file: "Fajl", | file: "Fajl", | ||||
| files: "Fajlovi", | files: "Fajlovi", | ||||
| documents: "| Dokumenti", | documents: "| Dokumenti", | ||||
| extension: "Ekstenzija", | extension: "Ekstenzija", | ||||
| tags: "Tagovi", | tags: "Tagovi", | ||||
| search: "Pretraži" | |||||
| search: "Pretraži", | |||||
| tag:"Tag" | |||||
| }, | }, | ||||
| }; | }; |
| createCategoryReq, | createCategoryReq, | ||||
| setCategoriesReq, | setCategoriesReq, | ||||
| } from "../../store/actions/categories/categoriesAction"; | } from "../../store/actions/categories/categoriesAction"; | ||||
| import { createTagReq } from "../../store/actions/tags/tagsAction"; | |||||
| import { | import { | ||||
| selectCategories, | selectCategories, | ||||
| selectChildParentRelations, | selectChildParentRelations, | ||||
| const dispatch = useDispatch(); | const dispatch = useDispatch(); | ||||
| const [trigger, setTrigger] = useState(0); | const [trigger, setTrigger] = useState(0); | ||||
| const [openCreateCategoryModal, setOpenCreateCategoryModal] = useState(false); | const [openCreateCategoryModal, setOpenCreateCategoryModal] = useState(false); | ||||
| const [openCreateTagModal, setOpenCreateTagModal] = useState(false); | |||||
| const [createCategoryName, setCreateCategoryName] = useState(""); | const [createCategoryName, setCreateCategoryName] = useState(""); | ||||
| const [createTagName, setCreateTagName] = useState(""); | |||||
| let { id } = useParams(); | let { id } = useParams(); | ||||
| const theme = useTheme(); | const theme = useTheme(); | ||||
| const matches = useMediaQuery(theme.breakpoints.down("370")); | const matches = useMediaQuery(theme.breakpoints.down("370")); | ||||
| setOpenCreateCategoryModal((oldState) => !oldState); | setOpenCreateCategoryModal((oldState) => !oldState); | ||||
| }; | }; | ||||
| const changeOpenCreateTagModal = () => { | |||||
| setOpenCreateTagModal((oldState) => !oldState); | |||||
| }; | |||||
| const getNameHandler = (name) => { | const getNameHandler = (name) => { | ||||
| if (matches) { | if (matches) { | ||||
| if (name.length > 7) return name.substr(0, 7) + "..."; | if (name.length > 7) return name.substr(0, 7) + "..."; | ||||
| setOpenCreateCategoryModal(false); | setOpenCreateCategoryModal(false); | ||||
| }; | }; | ||||
| const onSuccessCreatingTagHandler = () => { | |||||
| setOpenCreateTagModal(false); | |||||
| }; | |||||
| const createCategoryHandler = () => { | const createCategoryHandler = () => { | ||||
| dispatch( | dispatch( | ||||
| createCategoryReq({ | createCategoryReq({ | ||||
| setCreateCategoryName(""); | setCreateCategoryName(""); | ||||
| }; | }; | ||||
| const createTagHandler = () => { | |||||
| dispatch( | |||||
| createTagReq({ | |||||
| name: createTagName, | |||||
| onSuccess: onSuccessCreatingTagHandler, | |||||
| }) | |||||
| ); | |||||
| setCreateTagName(""); | |||||
| }; | |||||
| const ColoredLine = () => ( | const ColoredLine = () => ( | ||||
| <hr | <hr | ||||
| style={{ | style={{ | ||||
| return ( | return ( | ||||
| <> | <> | ||||
| <div className="l-t-rectangle"></div> | |||||
| <div className="r-b-rectangle" style={{width:matches ? 100 : 180}}></div> | |||||
| <div | |||||
| className="l-t-rectangle" | |||||
| style={{ height: matches ? 140 : 180 }} | |||||
| ></div> | |||||
| <div | |||||
| className="r-b-rectangle" | |||||
| style={{ width: matches ? 100 : 180 }} | |||||
| ></div> | |||||
| <CustomModal | <CustomModal | ||||
| classes="files-custom-modal" | classes="files-custom-modal" | ||||
| open={openCreateCategoryModal} | open={openCreateCategoryModal} | ||||
| </Button> | </Button> | ||||
| </div> | </div> | ||||
| </CustomModal> | </CustomModal> | ||||
| <CustomModal | |||||
| classes="files-custom-modal" | |||||
| open={openCreateTagModal} | |||||
| onCloseModal={changeOpenCreateTagModal} | |||||
| > | |||||
| <div className="add-pattern-modal-header"> | |||||
| <div className="add-pattern-modal-header-title"> | |||||
| <div className="add-pattern-modal-header-title-image"> | |||||
| <img src={plusIcon} alt="plus" /> | |||||
| </div> | |||||
| <div className="add-pattern-modal-header-title-title"> | |||||
| <p>{t("files.createTagModalTitle")}</p> | |||||
| </div> | |||||
| </div> | |||||
| <div | |||||
| className="add-pattern-modal-header-close" | |||||
| onClick={changeOpenCreateTagModal} | |||||
| > | |||||
| <img src={xIcon} alt="close" /> | |||||
| </div> | |||||
| </div> | |||||
| <div className="add-category-input"> | |||||
| <input | |||||
| type="text" | |||||
| placeholder={t("files.createTagModalPlaceholder")} | |||||
| value={createTagName} | |||||
| onChange={(e) => setCreateTagName(e.target.value)} | |||||
| /> | |||||
| </div> | |||||
| <div className="files-category-custom-modal-buttons"> | |||||
| <Button | |||||
| type="button" | |||||
| variant="contained" | |||||
| className="c-btn c-btn--primary-outlined" | |||||
| onClick={changeOpenCreateTagModal} | |||||
| > | |||||
| {t("files.close")} | |||||
| </Button> | |||||
| <Button | |||||
| type="button" | |||||
| variant="contained" | |||||
| className="c-btn c-btn--primary" | |||||
| onClick={createTagHandler} | |||||
| > | |||||
| {t("files.createTagModalSubmitButton")} | |||||
| </Button> | |||||
| </div> | |||||
| </CustomModal> | |||||
| <div | <div | ||||
| className="pl-144" | className="pl-144" | ||||
| style={{ paddingTop: "36px" }} | style={{ paddingTop: "36px" }} | ||||
| <div | <div | ||||
| style={{ | style={{ | ||||
| display: "flex", | display: "flex", | ||||
| alignItems: "center", | |||||
| alignItems: matches ? "flex-start" : "center", | |||||
| flexDirection: matches ? "column" : "row", | |||||
| justifyContent: "space-between", | justifyContent: "space-between", | ||||
| marginBottom: "15px", | marginBottom: "15px", | ||||
| }} | }} | ||||
| > | > | ||||
| + {t("files.category")} | + {t("files.category")} | ||||
| </IconButton> | </IconButton> | ||||
| <IconButton | |||||
| className={ | |||||
| `c-btn ads-page-btn c-btn--primary filesPage ` + | |||||
| (matches ? "files-button-responsive" : "add-ad-btn") | |||||
| } | |||||
| onClick={changeOpenCreateTagModal} | |||||
| > | |||||
| + {t("files.tag")} | |||||
| </IconButton> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <ColoredLine /> | <ColoredLine /> |
| import { getRequest } from "."; | |||||
| import { getRequest, postRequest } from "."; | |||||
| import apiEndpoints from "./apiEndpoints"; | import apiEndpoints from "./apiEndpoints"; | ||||
| export const getFileFilters = () => getRequest(apiEndpoints.fileTags.filters); | export const getFileFilters = () => getRequest(apiEndpoints.fileTags.filters); | ||||
| export const getAllTags = () => | |||||
| getRequest(apiEndpoints.tags.allTags); | |||||
| export const getAllTags = () => getRequest(apiEndpoints.tags.allTags); | |||||
| export const createTagRequest = (payload) => | |||||
| postRequest(apiEndpoints.fileTags.filters, payload); |
| FETCH_TAGS_ERR, | FETCH_TAGS_ERR, | ||||
| CHANGE_TAG_ISCHECKED_VALUE, | CHANGE_TAG_ISCHECKED_VALUE, | ||||
| RESET_CHECKED_TAGS, | RESET_CHECKED_TAGS, | ||||
| CREATE_TAG_ERR, | |||||
| CREATE_TAG_REQ, | |||||
| CREATE_TAG_SUCCESS, | |||||
| } from "./tagsActionConstants"; | } from "./tagsActionConstants"; | ||||
| export const setTagsReq = () => ({ | export const setTagsReq = () => ({ | ||||
| export const resetIsCheckedTagsValue = () => ({ | export const resetIsCheckedTagsValue = () => ({ | ||||
| type: RESET_CHECKED_TAGS, | type: RESET_CHECKED_TAGS, | ||||
| }); | }); | ||||
| export const createTagReq = (payload) => ({ | |||||
| type: CREATE_TAG_REQ, | |||||
| payload, | |||||
| }); | |||||
| export const createTagError = () => ({ | |||||
| type: CREATE_TAG_ERR, | |||||
| }); | |||||
| export const setCreateTag = (payload) => ({ | |||||
| type: CREATE_TAG_SUCCESS, | |||||
| payload, | |||||
| }); |
| } from "../actionHelpers"; | } from "../actionHelpers"; | ||||
| const FETCH_TAGS_SCOPE = "FETCH_TAGS"; | const FETCH_TAGS_SCOPE = "FETCH_TAGS"; | ||||
| const CREATE_TAG_SCOPE = "CREATE_TAG"; | |||||
| export const FETCH_TAGS_REQ = createFetchType(FETCH_TAGS_SCOPE); | export const FETCH_TAGS_REQ = createFetchType(FETCH_TAGS_SCOPE); | ||||
| export const FETCH_TAGS_ERR = createErrorType(FETCH_TAGS_SCOPE); | export const FETCH_TAGS_ERR = createErrorType(FETCH_TAGS_SCOPE); | ||||
| export const CHANGE_TAG_ISCHECKED_VALUE = "CHANGE_TAG_ISCHECKED_VALUE"; | export const CHANGE_TAG_ISCHECKED_VALUE = "CHANGE_TAG_ISCHECKED_VALUE"; | ||||
| export const RESET_CHECKED_TAGS = "RESET_CHECKED_TAGS"; | export const RESET_CHECKED_TAGS = "RESET_CHECKED_TAGS"; | ||||
| export const CREATE_TAG_REQ = createFetchType(CREATE_TAG_SCOPE); | |||||
| export const CREATE_TAG_ERR = createErrorType(CREATE_TAG_SCOPE); | |||||
| export const CREATE_TAG_SUCCESS = createSuccessType(CREATE_TAG_SCOPE); |
| FETCH_TAGS_SUCCESS, | FETCH_TAGS_SUCCESS, | ||||
| CHANGE_TAG_ISCHECKED_VALUE, | CHANGE_TAG_ISCHECKED_VALUE, | ||||
| RESET_CHECKED_TAGS, | RESET_CHECKED_TAGS, | ||||
| CREATE_TAG_ERR, | |||||
| CREATE_TAG_SUCCESS, | |||||
| } from "../../actions/tags/tagsActionConstants"; | } from "../../actions/tags/tagsActionConstants"; | ||||
| import createReducer from "../../utils/createReducer"; | import createReducer from "../../utils/createReducer"; | ||||
| [FETCH_TAGS_ERR]: setTagsErrorMessage, | [FETCH_TAGS_ERR]: setTagsErrorMessage, | ||||
| [CHANGE_TAG_ISCHECKED_VALUE]: setIsCheckedTags, | [CHANGE_TAG_ISCHECKED_VALUE]: setIsCheckedTags, | ||||
| [RESET_CHECKED_TAGS]: resetIsCheckedTags, | [RESET_CHECKED_TAGS]: resetIsCheckedTags, | ||||
| [CREATE_TAG_SUCCESS]: setCreateTagReducer, | |||||
| [CREATE_TAG_ERR]: setCreateTagErrorMessage, | |||||
| }, | }, | ||||
| initialState | initialState | ||||
| ); | ); | ||||
| } | } | ||||
| function setIsCheckedTags(state, action) { | function setIsCheckedTags(state, action) { | ||||
| const tmpIndex = state.tags.findIndex( | |||||
| (x) => x.id === action.payload | |||||
| ); | |||||
| const tmpIndex = state.tags.findIndex((x) => x.id === action.payload); | |||||
| if (tmpIndex === -1) { | if (tmpIndex === -1) { | ||||
| return state; | return state; | ||||
| tags: state.tags.map((tag) => ({ ...tag, isChecked: false })), | tags: state.tags.map((tag) => ({ ...tag, isChecked: false })), | ||||
| }; | }; | ||||
| } | } | ||||
| function setCreateTagReducer(state) { | |||||
| return { | |||||
| ...state, | |||||
| }; | |||||
| } | |||||
| function setCreateTagErrorMessage(state, action) { | |||||
| return { | |||||
| ...state, | |||||
| errorMessage: action.payload, | |||||
| }; | |||||
| } |
| import { all, call, put, takeLatest, takeEvery } from "redux-saga/effects"; | import { all, call, put, takeLatest, takeEvery } from "redux-saga/effects"; | ||||
| import { setTags, setTagsError } from "../actions/tags/tagsAction"; | |||||
| import { | |||||
| setTags, | |||||
| setTagsError, | |||||
| setCreateTag, | |||||
| createTagError, | |||||
| } from "../actions/tags/tagsAction"; | |||||
| import { authScopeStringGetHelper } from "../../util/helpers/authScopeHelpers"; | import { authScopeStringGetHelper } from "../../util/helpers/authScopeHelpers"; | ||||
| import { JWT_TOKEN } from "../../constants/localStorage"; | import { JWT_TOKEN } from "../../constants/localStorage"; | ||||
| import { addHeaderToken } from "../../request"; | import { addHeaderToken } from "../../request"; | ||||
| import { rejectErrorCodeHelper } from "../../util/helpers/rejectErrorCodeHelper"; | import { rejectErrorCodeHelper } from "../../util/helpers/rejectErrorCodeHelper"; | ||||
| import { FETCH_TAGS_REQ } from "../actions/tags/tagsActionConstants"; | |||||
| import { FETCH_TAGS_REQ,CREATE_TAG_REQ } from "../actions/tags/tagsActionConstants"; | |||||
| import { getAllTags } from "../../request/tagsRequest"; | import { getAllTags } from "../../request/tagsRequest"; | ||||
| import { getFileFilters } from "../../request/tagsRequest"; | |||||
| import { getFileFilters, createTagRequest } from "../../request/tagsRequest"; | |||||
| import { FILE_FILTERS_REQ } from "../actions/files/fileActionConstants"; | import { FILE_FILTERS_REQ } from "../actions/files/fileActionConstants"; | ||||
| import { | import { | ||||
| getFileFiltersError, | getFileFiltersError, | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| export function* createTagSaga({ payload }) { | |||||
| console.log("Payload je to",payload) | |||||
| try { | |||||
| const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN); | |||||
| yield call(addHeaderToken, JwtToken); | |||||
| yield call(createTagRequest, { | |||||
| name: payload.name, | |||||
| }); | |||||
| yield put(setCreateTag()); | |||||
| if (payload.onSuccess) yield call(payload.onSuccess); | |||||
| } catch (error) { | |||||
| const errorMessage = yield call(rejectErrorCodeHelper, error); | |||||
| yield put(createTagError(errorMessage)); | |||||
| } | |||||
| } | |||||
| export default function* tagsSaga() { | export default function* tagsSaga() { | ||||
| yield all([takeLatest(FETCH_TAGS_REQ, getTags)]); | yield all([takeLatest(FETCH_TAGS_REQ, getTags)]); | ||||
| yield all([takeEvery(FILE_FILTERS_REQ, getFileFiltersGen)]); | yield all([takeEvery(FILE_FILTERS_REQ, getFileFiltersGen)]); | ||||
| yield all([takeEvery(CREATE_TAG_REQ, createTagSaga)]); | |||||
| } | } |