From de6039fff365feb851ba311729e34439e5045fdd Mon Sep 17 00:00:00 2001 From: Clement Date: Mon, 23 Aug 2021 22:58:50 +0800 Subject: [PATCH 01/11] Create family-member.tsx --- .../entities/club-family/family-member.tsx | 44 +++++++++++++++++++ .../webapp/app/entities/club-family/index.tsx | 3 +- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 src/main/webapp/app/entities/club-family/family-member.tsx diff --git a/src/main/webapp/app/entities/club-family/family-member.tsx b/src/main/webapp/app/entities/club-family/family-member.tsx new file mode 100644 index 00000000..98b645d5 --- /dev/null +++ b/src/main/webapp/app/entities/club-family/family-member.tsx @@ -0,0 +1,44 @@ +import React from 'react'; + +import { Link, RouteComponentProps } from 'react-router-dom'; +import { Button, Row, Col } from 'reactstrap'; +import { Translate } from 'react-jhipster'; +import { connect } from 'react-redux'; +import { IRootState } from 'app/shared/reducers'; + +import AuthorizationChecker from 'app/shared/components/authorization-checker/authorization-checker'; +import CCRole from 'app/shared/model/enum/cc-role.enum'; +import EventRole from 'app/shared/model/enum/event-role.enum'; + +export interface IFamilyMemberProps extends StateProps, DispatchProps, RouteComponentProps {} + +class FamilyMember extends React.Component { + constructor(props: IFamilyMemberProps) { + super(props); + } + render() { + return ( +
+ + +

Bi Mu

+ + + Add + + + +
+
+ ); + } +} + +const mapStateToProps = (storeState: IRootState) => ({}); + +const mapDispatchToProps = {}; + +type StateProps = ReturnType; +type DispatchProps = typeof mapDispatchToProps; + +export default connect(mapStateToProps, mapDispatchToProps)(FamilyMember); diff --git a/src/main/webapp/app/entities/club-family/index.tsx b/src/main/webapp/app/entities/club-family/index.tsx index fd0dfada..58428337 100644 --- a/src/main/webapp/app/entities/club-family/index.tsx +++ b/src/main/webapp/app/entities/club-family/index.tsx @@ -6,11 +6,12 @@ import ErrorBoundaryRoute from 'app/shared/error/error-boundary-route'; import ClubFamily from './club-family'; import ClubFamilyDetail from './club-family-detail'; import FamilyMemberCreate from './family-member-create'; +import FamilyMember from './family-member'; const Routes: React.FC = ({ match }) => ( <> - + From 9af789f469526e760378ebfe7bfd468b575a3148 Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 31 Aug 2021 14:56:12 +0800 Subject: [PATCH 02/11] WIP: Created Member Card component. New action to get users with family code --- .../entities/club-family/family-member.tsx | 44 +++++++++++++------ .../app/entities/club-family/member-card.tsx | 40 +++++++++++++++++ .../user-cc-info/user-cc-info.reducer.ts | 8 +++- .../webapp/app/shared/type/custom-action.ts | 4 +- 4 files changed, 80 insertions(+), 16 deletions(-) create mode 100644 src/main/webapp/app/entities/club-family/member-card.tsx diff --git a/src/main/webapp/app/entities/club-family/family-member.tsx b/src/main/webapp/app/entities/club-family/family-member.tsx index 98b645d5..a543f63c 100644 --- a/src/main/webapp/app/entities/club-family/family-member.tsx +++ b/src/main/webapp/app/entities/club-family/family-member.tsx @@ -9,34 +9,50 @@ import { IRootState } from 'app/shared/reducers'; import AuthorizationChecker from 'app/shared/components/authorization-checker/authorization-checker'; import CCRole from 'app/shared/model/enum/cc-role.enum'; import EventRole from 'app/shared/model/enum/event-role.enum'; +import MemberCard from './member-card'; -export interface IFamilyMemberProps extends StateProps, DispatchProps, RouteComponentProps {} +import { getUsersWithFamilyCode } from 'app/entities/user-cc-info/user-cc-info.reducer'; + +export interface IFamilyMemberProps extends StateProps, DispatchProps, RouteComponentProps<{ id: string }> {} class FamilyMember extends React.Component { constructor(props: IFamilyMemberProps) { super(props); } + + componentDidMount() { + this.props.getUsersWithFamilyCode(this.props.match.params.id); + } + render() { + const { users, match } = this.props; return ( -
- - -

Bi Mu

- - - Add - - - -
+
+

+ Bi Mu +

+
+ + + Add + + + {users.map(user => ( + + ))} +
); } } -const mapStateToProps = (storeState: IRootState) => ({}); +const mapStateToProps = (storeState: IRootState) => ({ + users: storeState.userCCInfo.entities, +}); -const mapDispatchToProps = {}; +const mapDispatchToProps = { + getUsersWithFamilyCode, +}; type StateProps = ReturnType; type DispatchProps = typeof mapDispatchToProps; diff --git a/src/main/webapp/app/entities/club-family/member-card.tsx b/src/main/webapp/app/entities/club-family/member-card.tsx new file mode 100644 index 00000000..5ac13ed5 --- /dev/null +++ b/src/main/webapp/app/entities/club-family/member-card.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import { Row, Col, Card, CardImg, Button } from 'reactstrap'; +// tslint:disable-next-line:no-unused-variable +import { Translate, TextFormat } from 'react-jhipster'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; + +import AuthorizationChecker from 'app/shared/components/authorization-checker/authorization-checker'; +import CCRole from 'app/shared/model/enum/cc-role.enum'; +import EventRole from 'app/shared/model/enum/event-role.enum'; +import { concatFullName } from 'app/shared/util/string-util'; + +import { IUserCCInfo } from 'app/shared/model/user-cc-info.model'; + +export interface IMemberCardProps { + userCCInfo: IUserCCInfo; +} + +const MemberCard: React.FC = ({ userCCInfo }) => { + return ( + + + + + + +
{concatFullName(userCCInfo.user?.firstName, userCCInfo.user?.lastName)}
+

{userCCInfo.familyRole ?? 'Member'}

+ + + + +
+
+ ); +}; + +export default MemberCard; diff --git a/src/main/webapp/app/entities/user-cc-info/user-cc-info.reducer.ts b/src/main/webapp/app/entities/user-cc-info/user-cc-info.reducer.ts index 46ea2264..d9ca4127 100644 --- a/src/main/webapp/app/entities/user-cc-info/user-cc-info.reducer.ts +++ b/src/main/webapp/app/entities/user-cc-info/user-cc-info.reducer.ts @@ -1,11 +1,12 @@ import axios, { AxiosError } from 'axios'; import { ICrudGetAction, ICrudGetAllAction, ICrudPutAction, ICrudDeleteAction } from 'react-jhipster'; +import { AnyAction } from 'redux'; import { cleanEntity } from 'app/shared/util/entity-utils'; import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util'; import { IUserCCInfo, defaultValue } from 'app/shared/model/user-cc-info.model'; -import { AnyAction } from 'redux'; +import { IGetUsersWithFamilyCode } from 'app/shared/type/custom-action'; export const ACTION_TYPES = { FETCH_USERCCINFO_LIST: 'userCCInfo/FETCH_USERCCINFO_LIST', @@ -125,6 +126,11 @@ export const getUsersWithoutFamily: ICrudGetAllAction = (page, size payload: axios.get(`${apiUrl}?clubFamilyCode.specified=false`), }); +export const getUsersWithFamilyCode: IGetUsersWithFamilyCode = familyCode => ({ + type: ACTION_TYPES.FETCH_USERCCINFO_LIST, + payload: axios.get(`${apiUrl}?clubFamilyCode.equals=${familyCode}`), +}); + export const createEntity: ICrudPutAction = entity => async dispatch => { const result = await dispatch({ type: ACTION_TYPES.CREATE_USERCCINFO, diff --git a/src/main/webapp/app/shared/type/custom-action.ts b/src/main/webapp/app/shared/type/custom-action.ts index afd98e9b..4e4a61ac 100644 --- a/src/main/webapp/app/shared/type/custom-action.ts +++ b/src/main/webapp/app/shared/type/custom-action.ts @@ -1,3 +1,5 @@ -import { IPayload } from 'react-jhipster'; +import { IPayload, IPayloadResult } from 'react-jhipster'; export declare type IGetEntityWithoutParams = () => IPayload | ((dispatch: any) => IPayload); + +export declare type IGetUsersWithFamilyCode = (familyCode: string) => IPayload | IPayloadResult; From 2a936c6d8a070c9d9a42510bc825e2b4d18bec1b Mon Sep 17 00:00:00 2001 From: Clement Date: Thu, 9 Sep 2021 01:25:41 +0800 Subject: [PATCH 03/11] Completed Advanced Search Modal UI. Update family-member-create handleClose's route. --- src/main/webapp/app/_bootstrap-variables.scss | 7 +- src/main/webapp/app/config/icon-loader.ts | 4 +- .../club-family/family-member-create.tsx | 4 +- .../entities/club-family/family-member.scss | 15 +++ .../entities/club-family/family-member.tsx | 74 +++++++++++--- .../app/entities/club-family/member-card.tsx | 41 ++++---- .../user-cc-info/user-cc-info.reducer.ts | 49 ++++++++- .../filterSearchBar/filterSearchBar.scss | 23 +++++ .../filterSearchBar/filterSearchBar.tsx | 99 +++++++++++++++++++ .../webapp/app/shared/type/custom-action.ts | 2 +- src/main/webapp/app/styles/custom.scss | 10 ++ 11 files changed, 285 insertions(+), 43 deletions(-) create mode 100644 src/main/webapp/app/entities/club-family/family-member.scss create mode 100644 src/main/webapp/app/shared/components/filterSearchBar/filterSearchBar.scss create mode 100644 src/main/webapp/app/shared/components/filterSearchBar/filterSearchBar.tsx diff --git a/src/main/webapp/app/_bootstrap-variables.scss b/src/main/webapp/app/_bootstrap-variables.scss index eaf13959..063eb76a 100644 --- a/src/main/webapp/app/_bootstrap-variables.scss +++ b/src/main/webapp/app/_bootstrap-variables.scss @@ -15,5 +15,10 @@ $theme-colors: ( 'action': #1db2a1, 'cancel': #dd5959, 'expense': #c21717, - 'income': #0e516d + 'income': #0e516d, + 'bimu': #7cc250, + 'jinlong': #b78cfb, + 'qicai': #71ccff, + 'nemo': #ff9e3c, + 'peacock': #ff7d7d, ); diff --git a/src/main/webapp/app/config/icon-loader.ts b/src/main/webapp/app/config/icon-loader.ts index 3bb0e9c4..61044574 100644 --- a/src/main/webapp/app/config/icon-loader.ts +++ b/src/main/webapp/app/config/icon-loader.ts @@ -50,6 +50,7 @@ import { faWhatsappSquare } from '@fortawesome/free-brands-svg-icons/faWhatsappS import { library } from '@fortawesome/fontawesome-svg-core'; import { faSortAmountUp } from '@fortawesome/free-solid-svg-icons/faSortAmountUp'; import { faEuroSign } from '@fortawesome/free-solid-svg-icons/faEuroSign'; +import { faFilter } from '@fortawesome/free-solid-svg-icons/faFilter'; export const loadIcons = () => { library.add( @@ -102,6 +103,7 @@ export const loadIcons = () => { faSortAmountUp, faPlaneDeparture, faEuroSign, - faFish + faFish, + faFilter ); }; diff --git a/src/main/webapp/app/entities/club-family/family-member-create.tsx b/src/main/webapp/app/entities/club-family/family-member-create.tsx index 575978f5..f212cd58 100644 --- a/src/main/webapp/app/entities/club-family/family-member-create.tsx +++ b/src/main/webapp/app/entities/club-family/family-member-create.tsx @@ -25,7 +25,7 @@ class FamilyMemberCreate extends React.Component { } handleClose = () => { - this.props.history.push(`/entity/members/club-family/${this.props.match.params.id}`); + this.props.history.push(`/entity/members/cc-family/${this.props.match.params.id}`); }; componentDidMount() { @@ -112,7 +112,7 @@ class FamilyMemberCreate extends React.Component { className="general-button--width" tag={Link} id="cancel-save" - to={`/entity/members/club-family/${familyCode}`} + to={`/entity/members/cc-family/${familyCode}`} replace color="cancel" > diff --git a/src/main/webapp/app/entities/club-family/family-member.scss b/src/main/webapp/app/entities/club-family/family-member.scss new file mode 100644 index 00000000..2d4394aa --- /dev/null +++ b/src/main/webapp/app/entities/club-family/family-member.scss @@ -0,0 +1,15 @@ +.search-bar-prepend span { + background-color: white; + border-right: none; +} + +.search-bar-input { + border-left: none; + border-right: none; +} + +.search-bar-append { + background-color: white; + border-left: none; + border-color: #ced4da; +} diff --git a/src/main/webapp/app/entities/club-family/family-member.tsx b/src/main/webapp/app/entities/club-family/family-member.tsx index a543f63c..c913e208 100644 --- a/src/main/webapp/app/entities/club-family/family-member.tsx +++ b/src/main/webapp/app/entities/club-family/family-member.tsx @@ -1,8 +1,9 @@ import React from 'react'; import { Link, RouteComponentProps } from 'react-router-dom'; -import { Button, Row, Col } from 'reactstrap'; -import { Translate } from 'react-jhipster'; +import { Button, Row, Col, InputGroupAddon, InputGroup, Input } from 'reactstrap'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Translate, translate } from 'react-jhipster'; import { connect } from 'react-redux'; import { IRootState } from 'app/shared/reducers'; @@ -10,48 +11,93 @@ import AuthorizationChecker from 'app/shared/components/authorization-checker/au import CCRole from 'app/shared/model/enum/cc-role.enum'; import EventRole from 'app/shared/model/enum/event-role.enum'; import MemberCard from './member-card'; +import FilterSearchBar from 'app/shared/components/filterSearchBar/filterSearchBar'; +import './family-member.scss'; -import { getUsersWithFamilyCode } from 'app/entities/user-cc-info/user-cc-info.reducer'; +import { + getUsersWithFamilyCode, + setSelectedYearSessionFilter, + getYearSessionOptions, + getEntities, +} from 'app/entities/user-cc-info/user-cc-info.reducer'; +import { getClubFamilyDetails } from 'app/shared/services/club-family-info.service'; export interface IFamilyMemberProps extends StateProps, DispatchProps, RouteComponentProps<{ id: string }> {} -class FamilyMember extends React.Component { +export interface IFamilyMemberState { + searchedName: string; +} +class FamilyMember extends React.Component { constructor(props: IFamilyMemberProps) { super(props); + this.state = { + searchedName: '', + }; } - componentDidMount() { - this.props.getUsersWithFamilyCode(this.props.match.params.id); + async componentDidMount() { + await this.props.getYearSessionOptions(0, 12, 'value,desc'); + this.props.getUsersWithFamilyCode(this.props.match.params.id, this.props.selectedYearSessionFilter); } + setYearSession = async (yearSession: string): Promise => { + await this.props.setSelectedYearSessionFilter(yearSession); + this.props.getUsersWithFamilyCode(this.props.match.params.id, this.props.selectedYearSessionFilter); + }; + render() { - const { users, match } = this.props; + const { users, yearSessionOptions, selectedYearSessionFilter, match } = this.props; + const familyName = getClubFamilyDetails(match.params.id).name; return (

- Bi Mu + {familyName ? translate(familyName) : null}

- + Add - {users.map(user => ( - - ))} + {/* */} + + + 🔎 + + + + + + + {users && users.length > 0 ? ( +
+ {users.map(user => ( + + ))} +
+ ) : ( +
+ No Event Activities found +
+ )}
); } } -const mapStateToProps = (storeState: IRootState) => ({ - users: storeState.userCCInfo.entities, +const mapStateToProps = ({ userCCInfo }: IRootState) => ({ + users: userCCInfo.entities, + selectedYearSessionFilter: userCCInfo.selectedYearSessionFilter, + yearSessionOptions: userCCInfo.yearSessionOptions, }); const mapDispatchToProps = { getUsersWithFamilyCode, + setSelectedYearSessionFilter, + getYearSessionOptions, }; type StateProps = ReturnType; diff --git a/src/main/webapp/app/entities/club-family/member-card.tsx b/src/main/webapp/app/entities/club-family/member-card.tsx index 5ac13ed5..66336400 100644 --- a/src/main/webapp/app/entities/club-family/member-card.tsx +++ b/src/main/webapp/app/entities/club-family/member-card.tsx @@ -1,3 +1,4 @@ +import 'app/styles/custom.scss'; import React from 'react'; import { Link } from 'react-router-dom'; import { Row, Col, Card, CardImg, Button } from 'reactstrap'; @@ -16,25 +17,25 @@ export interface IMemberCardProps { userCCInfo: IUserCCInfo; } -const MemberCard: React.FC = ({ userCCInfo }) => { - return ( - - - - - - -
{concatFullName(userCCInfo.user?.firstName, userCCInfo.user?.lastName)}
-

{userCCInfo.familyRole ?? 'Member'}

- - - - -
-
- ); -}; +const MemberCard: React.FC = ({ userCCInfo }) => ( + + + +
+ +
+ + +
{concatFullName(userCCInfo.user?.firstName, userCCInfo.user?.lastName)}
+

{userCCInfo.familyRole ?? 'Member'}

+ + + + +
+
+); export default MemberCard; diff --git a/src/main/webapp/app/entities/user-cc-info/user-cc-info.reducer.ts b/src/main/webapp/app/entities/user-cc-info/user-cc-info.reducer.ts index d9ca4127..f8edec59 100644 --- a/src/main/webapp/app/entities/user-cc-info/user-cc-info.reducer.ts +++ b/src/main/webapp/app/entities/user-cc-info/user-cc-info.reducer.ts @@ -14,6 +14,8 @@ export const ACTION_TYPES = { CREATE_USERCCINFO: 'userCCInfo/CREATE_USERCCINFO', UPDATE_USERCCINFO: 'userCCInfo/UPDATE_USERCCINFO', DELETE_USERCCINFO: 'userCCInfo/DELETE_USERCCINFO', + FETCH_YEAR_SESSION_OPTIONS: 'FETCH_YEAR_SESSION_OPTIONS', + SET_SELECTED_YEAR_SESSION_FILTER: 'SET_SELECTED_YEAR_SESSION_FILTER', RESET: 'userCCInfo/RESET', }; @@ -24,6 +26,8 @@ const initialState: IUserCCInfoState = { entity: defaultValue, updating: false, updateSuccess: false, + yearSessionOptions: [], + selectedYearSessionFilter: '', }; export interface IUserCCInfoState { @@ -33,6 +37,8 @@ export interface IUserCCInfoState { entity: Readonly; updating: boolean; updateSuccess: boolean; + yearSessionOptions: string[]; + selectedYearSessionFilter: string; } // Reducer @@ -41,6 +47,7 @@ export default (state: IUserCCInfoState = initialState, action: AnyAction): IUse switch (action.type) { case REQUEST(ACTION_TYPES.FETCH_USERCCINFO_LIST): case REQUEST(ACTION_TYPES.FETCH_USERCCINFO): + case REQUEST(ACTION_TYPES.FETCH_YEAR_SESSION_OPTIONS): return { ...state, errResponse: null, @@ -61,6 +68,7 @@ export default (state: IUserCCInfoState = initialState, action: AnyAction): IUse case FAILURE(ACTION_TYPES.CREATE_USERCCINFO): case FAILURE(ACTION_TYPES.UPDATE_USERCCINFO): case FAILURE(ACTION_TYPES.DELETE_USERCCINFO): + case FAILURE(ACTION_TYPES.FETCH_YEAR_SESSION_OPTIONS): return { ...state, loading: false, @@ -95,6 +103,19 @@ export default (state: IUserCCInfoState = initialState, action: AnyAction): IUse updateSuccess: true, entity: {}, }; + case SUCCESS(ACTION_TYPES.FETCH_YEAR_SESSION_OPTIONS): + return { + ...state, + loading: false, + yearSessionOptions: action.payload.data, + selectedYearSessionFilter: action.payload.data[0], + }; + case ACTION_TYPES.SET_SELECTED_YEAR_SESSION_FILTER: + const { selectedYearSession } = action.payload; + return { + ...state, + selectedYearSessionFilter: selectedYearSession, + }; case ACTION_TYPES.RESET: return { ...initialState, @@ -126,10 +147,16 @@ export const getUsersWithoutFamily: ICrudGetAllAction = (page, size payload: axios.get(`${apiUrl}?clubFamilyCode.specified=false`), }); -export const getUsersWithFamilyCode: IGetUsersWithFamilyCode = familyCode => ({ - type: ACTION_TYPES.FETCH_USERCCINFO_LIST, - payload: axios.get(`${apiUrl}?clubFamilyCode.equals=${familyCode}`), -}); +export const getUsersWithFamilyCode: IGetUsersWithFamilyCode = (familyCode: string, yearSession?: string) => { + let requestUrl = `${apiUrl}?clubFamilyCode.equals=${familyCode}`; + if (yearSession) { + requestUrl = `${requestUrl}&yearSession.equals=${yearSession}`; + } + return { + type: ACTION_TYPES.FETCH_USERCCINFO_LIST, + payload: axios.get(requestUrl), + }; +}; export const createEntity: ICrudPutAction = entity => async dispatch => { const result = await dispatch({ @@ -159,6 +186,20 @@ export const deleteEntity: ICrudDeleteAction = id => async dispatch return result; }; +export const getYearSessionOptions: ICrudGetAllAction = (page, size, sort) => ({ + type: ACTION_TYPES.FETCH_YEAR_SESSION_OPTIONS, + payload: axios.get( + `api/year-sessions/values?cacheBuster=${new Date().getTime()}${sort ? `&page=${page}&size=${size}&sort=${sort}` : ''}` + ), +}); + +export const setSelectedYearSessionFilter = (selectedYearSession: string) => ({ + type: ACTION_TYPES.SET_SELECTED_YEAR_SESSION_FILTER, + payload: { + selectedYearSession, + }, +}); + export const reset = () => ({ type: ACTION_TYPES.RESET, }); diff --git a/src/main/webapp/app/shared/components/filterSearchBar/filterSearchBar.scss b/src/main/webapp/app/shared/components/filterSearchBar/filterSearchBar.scss new file mode 100644 index 00000000..3659a5f9 --- /dev/null +++ b/src/main/webapp/app/shared/components/filterSearchBar/filterSearchBar.scss @@ -0,0 +1,23 @@ +.filter-bar { + background-color: white; + border-color: #07ade1; + width: 100%; + padding: 0.5rem 0.75rem; + cursor: text; +} + +.filter-bar-text { + color: #07ade1; + font-size: 14px; + line-height: 16px; +} + +.advanced-search-modal { + width: 90%; + margin: auto; +} + +.family-button-group button { + width: 5.5rem; + font-weight: 500; +} diff --git a/src/main/webapp/app/shared/components/filterSearchBar/filterSearchBar.tsx b/src/main/webapp/app/shared/components/filterSearchBar/filterSearchBar.tsx new file mode 100644 index 00000000..bc58f250 --- /dev/null +++ b/src/main/webapp/app/shared/components/filterSearchBar/filterSearchBar.tsx @@ -0,0 +1,99 @@ +import React from 'react'; +import { Button, Modal, ModalHeader, ModalBody, Label, Input } from 'reactstrap'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { AvFeedback, AvForm, AvGroup, AvInput, AvField } from 'availity-reactstrap-validation'; +import { Translate } from 'react-jhipster'; +import './filterSearchBar.scss'; + +interface IFilterSearchBarProps { + // onChange: () => void; +} +interface IFilterSearchBarState { + showOptions: boolean; +} + +class FilterSearchBar extends React.Component { + constructor(props: IFilterSearchBarProps) { + super(props); + this.state = { + showOptions: false, + }; + } + + showOptionsModal = (): void => { + this.setState({ + ...this.state, + showOptions: true, + }); + }; + + toggleShowOptions = (): void => { + this.setState({ + ...this.state, + showOptions: !this.state.showOptions, + }); + }; + + render() { + const { showOptions } = this.state; + return ( + <> + + + + + +

Advanced Search

+ + + + + + + + + + + +
CC Family
+
+ + + + + +
+
+
+ +   + +
+
+
+
+ + ); + } +} + +export default FilterSearchBar; diff --git a/src/main/webapp/app/shared/type/custom-action.ts b/src/main/webapp/app/shared/type/custom-action.ts index 4e4a61ac..57efd186 100644 --- a/src/main/webapp/app/shared/type/custom-action.ts +++ b/src/main/webapp/app/shared/type/custom-action.ts @@ -2,4 +2,4 @@ import { IPayload, IPayloadResult } from 'react-jhipster'; export declare type IGetEntityWithoutParams = () => IPayload | ((dispatch: any) => IPayload); -export declare type IGetUsersWithFamilyCode = (familyCode: string) => IPayload | IPayloadResult; +export declare type IGetUsersWithFamilyCode = (familyCode: string, yearSession?: string) => IPayload | IPayloadResult; diff --git a/src/main/webapp/app/styles/custom.scss b/src/main/webapp/app/styles/custom.scss index dc437360..f8a39e13 100644 --- a/src/main/webapp/app/styles/custom.scss +++ b/src/main/webapp/app/styles/custom.scss @@ -64,3 +64,13 @@ font-weight: 400; color: #7b7b7b; } + +.square-image { + position: relative; + padding-bottom: 100%; + overflow: hidden; +} + +.square-image img { + position: absolute; +} From 7d6c3e36e6750298a2617e001c334b2f425071f9 Mon Sep 17 00:00:00 2001 From: Clement Date: Sun, 19 Sep 2021 13:54:48 +0800 Subject: [PATCH 04/11] WIP: Working on filtering --- .../entities/club-family/family-member.scss | 4 + .../entities/club-family/family-member.tsx | 43 ++- .../user-cc-info/user-cc-info.reducer.ts | 24 +- .../filterSearchBar/filterSearchBar.tsx | 151 ++++++---- .../webapp/app/shared/type/custom-action.ts | 2 +- src/main/webapp/swagger-ui/index.html | 279 +++++++++--------- 6 files changed, 290 insertions(+), 213 deletions(-) diff --git a/src/main/webapp/app/entities/club-family/family-member.scss b/src/main/webapp/app/entities/club-family/family-member.scss index 2d4394aa..bd27d00e 100644 --- a/src/main/webapp/app/entities/club-family/family-member.scss +++ b/src/main/webapp/app/entities/club-family/family-member.scss @@ -13,3 +13,7 @@ border-left: none; border-color: #ced4da; } + +.search-bar-append:focus { + background-color: white; +} diff --git a/src/main/webapp/app/entities/club-family/family-member.tsx b/src/main/webapp/app/entities/club-family/family-member.tsx index c913e208..78954907 100644 --- a/src/main/webapp/app/entities/club-family/family-member.tsx +++ b/src/main/webapp/app/entities/club-family/family-member.tsx @@ -14,42 +14,56 @@ import MemberCard from './member-card'; import FilterSearchBar from 'app/shared/components/filterSearchBar/filterSearchBar'; import './family-member.scss'; -import { - getUsersWithFamilyCode, - setSelectedYearSessionFilter, - getYearSessionOptions, - getEntities, -} from 'app/entities/user-cc-info/user-cc-info.reducer'; +import { getUsersWithFilter, setSelectedYearSessionFilter, getYearSessionOptions } from 'app/entities/user-cc-info/user-cc-info.reducer'; import { getClubFamilyDetails } from 'app/shared/services/club-family-info.service'; export interface IFamilyMemberProps extends StateProps, DispatchProps, RouteComponentProps<{ id: string }> {} export interface IFamilyMemberState { - searchedName: string; + showModal: boolean; } class FamilyMember extends React.Component { constructor(props: IFamilyMemberProps) { super(props); this.state = { - searchedName: '', + showModal: false, }; } async componentDidMount() { await this.props.getYearSessionOptions(0, 12, 'value,desc'); - this.props.getUsersWithFamilyCode(this.props.match.params.id, this.props.selectedYearSessionFilter); + this.props.getUsersWithFilter(this.props.match.params.id); } setYearSession = async (yearSession: string): Promise => { await this.props.setSelectedYearSessionFilter(yearSession); - this.props.getUsersWithFamilyCode(this.props.match.params.id, this.props.selectedYearSessionFilter); + this.props.getUsersWithFilter(this.props.match.params.id); + }; + + showModal = (): void => { + this.setState({ + showModal: true, + }); + }; + + toggleModal = (): void => { + this.setState({ + showModal: !this.state.showModal, + }); }; render() { - const { users, yearSessionOptions, selectedYearSessionFilter, match } = this.props; + const { users, yearSessionOptions, selectedYearSessionFilter, getUsersWithFilter, match } = this.props; + const { showModal } = this.state; const familyName = getClubFamilyDetails(match.params.id).name; return (
+

{familyName ? translate(familyName) : null}

@@ -59,14 +73,13 @@ class FamilyMember extends React.ComponentAdd - {/* */} 🔎 - + - @@ -95,7 +108,7 @@ const mapStateToProps = ({ userCCInfo }: IRootState) => ({ }); const mapDispatchToProps = { - getUsersWithFamilyCode, + getUsersWithFilter, setSelectedYearSessionFilter, getYearSessionOptions, }; diff --git a/src/main/webapp/app/entities/user-cc-info/user-cc-info.reducer.ts b/src/main/webapp/app/entities/user-cc-info/user-cc-info.reducer.ts index f8edec59..6b16c9f7 100644 --- a/src/main/webapp/app/entities/user-cc-info/user-cc-info.reducer.ts +++ b/src/main/webapp/app/entities/user-cc-info/user-cc-info.reducer.ts @@ -6,7 +6,7 @@ import { cleanEntity } from 'app/shared/util/entity-utils'; import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util'; import { IUserCCInfo, defaultValue } from 'app/shared/model/user-cc-info.model'; -import { IGetUsersWithFamilyCode } from 'app/shared/type/custom-action'; +import { IGetUsersWithFilters } from 'app/shared/type/custom-action'; export const ACTION_TYPES = { FETCH_USERCCINFO_LIST: 'userCCInfo/FETCH_USERCCINFO_LIST', @@ -147,7 +147,7 @@ export const getUsersWithoutFamily: ICrudGetAllAction = (page, size payload: axios.get(`${apiUrl}?clubFamilyCode.specified=false`), }); -export const getUsersWithFamilyCode: IGetUsersWithFamilyCode = (familyCode: string, yearSession?: string) => { +export const getUsersWithFamilyCode: IGetUsersWithFilters = (familyCode: string, yearSession?: string) => { let requestUrl = `${apiUrl}?clubFamilyCode.equals=${familyCode}`; if (yearSession) { requestUrl = `${requestUrl}&yearSession.equals=${yearSession}`; @@ -158,6 +158,26 @@ export const getUsersWithFamilyCode: IGetUsersWithFamilyCode = (fam }; }; +export const getUsersWithFilter: any = (familyCode?: string, filters?: any) => { + let requestUrl = apiUrl; + + if (familyCode) { + requestUrl = `${apiUrl}?clubFamilyCode.equals=${familyCode}`; + } + if (filters) { + for (const filter in filters) { + if (filters[filter]) { + requestUrl = `${requestUrl}&${filter}.equals=${filters[filter]}`; + } + } + } + + return { + type: ACTION_TYPES.FETCH_USERCCINFO_LIST, + payload: axios.get(requestUrl), + }; +}; + export const createEntity: ICrudPutAction = entity => async dispatch => { const result = await dispatch({ type: ACTION_TYPES.CREATE_USERCCINFO, diff --git a/src/main/webapp/app/shared/components/filterSearchBar/filterSearchBar.tsx b/src/main/webapp/app/shared/components/filterSearchBar/filterSearchBar.tsx index bc58f250..fd845d2a 100644 --- a/src/main/webapp/app/shared/components/filterSearchBar/filterSearchBar.tsx +++ b/src/main/webapp/app/shared/components/filterSearchBar/filterSearchBar.tsx @@ -1,64 +1,98 @@ import React from 'react'; +import { connect } from 'react-redux'; import { Button, Modal, ModalHeader, ModalBody, Label, Input } from 'reactstrap'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { AvFeedback, AvForm, AvGroup, AvInput, AvField } from 'availity-reactstrap-validation'; import { Translate } from 'react-jhipster'; +import { IRootState } from 'app/shared/reducers'; +import { getYearSessionOptions } from 'app/entities/user-cc-info/user-cc-info.reducer'; +import { getEntities as getFacultyOptions } from 'app/entities/faculty/faculty.reducer'; +import { IFaculty } from 'app/shared/model/faculty.model'; + import './filterSearchBar.scss'; -interface IFilterSearchBarProps { - // onChange: () => void; +interface IFilterSearchBarProps extends StateProps, DispatchProps { + showModal: boolean; + toggleModal: () => void; + familyCode: string; + searchUsers: (familyCode: string, filters: any) => void; } + interface IFilterSearchBarState { - showOptions: boolean; + filters: { + userFirstName?: string; + userLastName?: string; + faculty?: IFaculty; + intakeYearSession?: string; + }; } class FilterSearchBar extends React.Component { constructor(props: IFilterSearchBarProps) { super(props); this.state = { - showOptions: false, + filters: { + userFirstName: '', + userLastName: '', + faculty: undefined, + intakeYearSession: '', + }, }; } - showOptionsModal = (): void => { - this.setState({ - ...this.state, - showOptions: true, - }); - }; + componentDidMount() { + this.props.getYearSessionOptions(0, 12, 'value,desc'); + this.props.getFacultyOptions(); + } - toggleShowOptions = (): void => { - this.setState({ - ...this.state, - showOptions: !this.state.showOptions, - }); + renderYearSessionOptions = () => this.props.yearSessionOptions.map(year => ); + + renderFacultyOptions = () => this.props.facultyOptions.map(faculty => ); + + searchEntities = (event: any, errors: any, values: any) => { + if (errors.length === 0) { + const { filters } = this.state; + const { familyCode, searchUsers } = this.props; + const entity = { + ...filters, + ...values, + }; + searchUsers(familyCode, entity); + this.props.toggleModal(); + } }; render() { - const { showOptions } = this.state; + const { showModal, familyCode } = this.props; return ( - <> - - - - - -

Advanced Search

- - - - - - - - - - + + + +

Advanced Search

+ + + + + + + + + + + {this.renderFacultyOptions()} + + + + + + {this.renderYearSessionOptions()} + + + {familyCode ? null : (
CC Family
@@ -79,21 +113,34 @@ class FilterSearchBar extends React.Component
-
- -   - -
-
-
-
- + )} +
+ +   + +
+
+
+
); } } -export default FilterSearchBar; +const mapStateToProps = ({ userCCInfo, faculty }: IRootState) => ({ + yearSessionOptions: userCCInfo.yearSessionOptions, + facultyOptions: faculty.entities, +}); + +const mapDispatchToProps = { + getYearSessionOptions, + getFacultyOptions, +}; + +type StateProps = ReturnType; +type DispatchProps = typeof mapDispatchToProps; + +export default connect(mapStateToProps, mapDispatchToProps)(FilterSearchBar); diff --git a/src/main/webapp/app/shared/type/custom-action.ts b/src/main/webapp/app/shared/type/custom-action.ts index 57efd186..d5d72aea 100644 --- a/src/main/webapp/app/shared/type/custom-action.ts +++ b/src/main/webapp/app/shared/type/custom-action.ts @@ -2,4 +2,4 @@ import { IPayload, IPayloadResult } from 'react-jhipster'; export declare type IGetEntityWithoutParams = () => IPayload | ((dispatch: any) => IPayload); -export declare type IGetUsersWithFamilyCode = (familyCode: string, yearSession?: string) => IPayload | IPayloadResult; +export declare type IGetUsersWithFilters = (familyCode: string, filters?: any) => IPayload | IPayloadResult; diff --git a/src/main/webapp/swagger-ui/index.html b/src/main/webapp/swagger-ui/index.html index 2345ea20..30b03fe4 100644 --- a/src/main/webapp/swagger-ui/index.html +++ b/src/main/webapp/swagger-ui/index.html @@ -1,28 +1,28 @@ - - + + Swagger UI - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -30,137 +30,130 @@ - + function maybePrefix(location, withRelativePath) { + var pat = /^https?:\/\//i; + if (pat.test(location)) { + return location; + } + return withRelativePath + location; + } + + function initializeBaseUrl() { + var relativeLocation = springfox.baseUrl(); + + $('#input_baseUrl').hide(); + + $.getJSON(relativeLocation + '/swagger-resources', function (data) { + var $urlDropdown = $('#select_baseUrl'); + $urlDropdown.empty(); + $.each(data, function (i, resource) { + var option = $('') + .attr('value', maybePrefix(resource.location, relativeLocation)) + .text(resource.name + ' (' + resource.location + ')'); + $urlDropdown.append(option); + }); + $urlDropdown.change(); + }); + } + }); + + - -