rudamentary mutli-post err handling
This commit is contained in:
parent
530593b721
commit
dac6daa933
|
@ -1,7 +1,7 @@
|
||||||
import {
|
import {
|
||||||
IS_SENDING_CSHIFT_REQUEST,
|
IS_SENDING_CSHIFT_REQUEST,
|
||||||
SET_CSHIFT_REQUEST_ERROR,
|
SET_CSHIFT_REQUEST_ERRORS,
|
||||||
CLEAR_CSHIFT_REQUEST_ERROR,
|
CLEAR_CSHIFT_REQUEST_ERRORS,
|
||||||
SET_CSHIFT_REQUEST_SUCCESS,
|
SET_CSHIFT_REQUEST_SUCCESS,
|
||||||
CLEAR_CSHIFT_REQUEST_SUCCESS,
|
CLEAR_CSHIFT_REQUEST_SUCCESS,
|
||||||
SET_FORM_EMPLOYEE_UUID,
|
SET_FORM_EMPLOYEE_UUID,
|
||||||
|
@ -14,6 +14,13 @@ import {
|
||||||
} from "../../constants/cShift.constants";
|
} from "../../constants/cShift.constants";
|
||||||
import { parseError } from "../common.actions";
|
import { parseError } from "../common.actions";
|
||||||
|
|
||||||
|
function transformError(error) {
|
||||||
|
if (error.get_price_uuid) {
|
||||||
|
error["Price"] = error.get_price_uuid;
|
||||||
|
delete error["get_price_uuid"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function isSendingCShiftRequest(sendingRequest) {
|
export function isSendingCShiftRequest(sendingRequest) {
|
||||||
return {
|
return {
|
||||||
type: IS_SENDING_CSHIFT_REQUEST,
|
type: IS_SENDING_CSHIFT_REQUEST,
|
||||||
|
@ -23,15 +30,25 @@ export function isSendingCShiftRequest(sendingRequest) {
|
||||||
|
|
||||||
export function setCShiftRequestError(exception) {
|
export function setCShiftRequestError(exception) {
|
||||||
let error = parseError(exception);
|
let error = parseError(exception);
|
||||||
|
transformError(error);
|
||||||
return {
|
return {
|
||||||
type: SET_CSHIFT_REQUEST_ERROR,
|
type: SET_CSHIFT_REQUEST_ERRORS,
|
||||||
data: error
|
data: [error]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setCShiftRequestErrors(exceptions) {
|
||||||
|
let errors = exceptions.map(exception => parseError(exception));
|
||||||
|
errors.forEach(error => transformError(error));
|
||||||
|
return {
|
||||||
|
type: SET_CSHIFT_REQUEST_ERRORS,
|
||||||
|
data: errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function clearCShiftRequestError() {
|
export function clearCShiftRequestError() {
|
||||||
return {
|
return {
|
||||||
type: CLEAR_CSHIFT_REQUEST_ERROR
|
type: CLEAR_CSHIFT_REQUEST_ERRORS
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +107,7 @@ export function setFormShiftDates(dates) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setClearCshiftState() {
|
export function setClearCShiftState() {
|
||||||
return {
|
return {
|
||||||
type: SET_CLEAR_CSHIFT_STATE
|
type: SET_CLEAR_CSHIFT_STATE
|
||||||
};
|
};
|
||||||
|
|
12
src/actions/cShift/saga.actions.js
Normal file
12
src/actions/cShift/saga.actions.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { CREATE_MULTIPLE_CSHIFT_REQUEST } from "../../constants/cShift.constants";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saga action for creating a list of shifts
|
||||||
|
* @param postBody[] array of post body for cshift post endpoint
|
||||||
|
*/
|
||||||
|
export function createMultipleCShiftRequest(postBodies) {
|
||||||
|
return {
|
||||||
|
type: CREATE_MULTIPLE_CSHIFT_REQUEST,
|
||||||
|
data: postBodies
|
||||||
|
};
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ const localStorage = global.process && process.env.NODE_ENV === "test"
|
||||||
require("localStorage")
|
require("localStorage")
|
||||||
: global.window.localStorage;
|
: global.window.localStorage;
|
||||||
|
|
||||||
function headers() {
|
export function headers() {
|
||||||
const token = localStorage.getItem("userToken") || "";
|
const token = localStorage.getItem("userToken") || "";
|
||||||
let header = {
|
let header = {
|
||||||
Accept: "application/json",
|
Accept: "application/json",
|
||||||
|
@ -59,3 +59,5 @@ export function del(url) {
|
||||||
.then(response => response.data)
|
.then(response => response.data)
|
||||||
.catch(error => Promise.reject(error));
|
.catch(error => Promise.reject(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default apiInstance;
|
||||||
|
|
19
src/api/cShift.api.js
Normal file
19
src/api/cShift.api.js
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { post } from "./baseApi";
|
||||||
|
|
||||||
|
export function createCShifts(postBodies) {
|
||||||
|
const cShiftUrl = `/cshift/`;
|
||||||
|
// return Promise.all(
|
||||||
|
// postBodies.map(postBody => post(cShiftUrl, postBody).catch(() => false))
|
||||||
|
// ).then(postResponses => {
|
||||||
|
// Promise.resolve(postResponses);
|
||||||
|
// });
|
||||||
|
return Promise.all(
|
||||||
|
postBodies.map(postBody =>
|
||||||
|
post(cShiftUrl, postBody).catch(err => {
|
||||||
|
return { error: true, ...err };
|
||||||
|
})
|
||||||
|
)
|
||||||
|
).then(resp => {
|
||||||
|
return Promise.resolve(resp);
|
||||||
|
});
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import {
|
||||||
Form,
|
Form,
|
||||||
Header,
|
Header,
|
||||||
Label,
|
Label,
|
||||||
|
Message,
|
||||||
TextArea
|
TextArea
|
||||||
} from "semantic-ui-react";
|
} from "semantic-ui-react";
|
||||||
|
|
||||||
|
@ -18,9 +19,11 @@ import {
|
||||||
setFormShiftStartTime,
|
setFormShiftStartTime,
|
||||||
setFormShiftDuration,
|
setFormShiftDuration,
|
||||||
setFormShiftNote,
|
setFormShiftNote,
|
||||||
setClearCshiftState,
|
setClearCShiftState,
|
||||||
setFormShiftDates
|
setFormShiftDates
|
||||||
} from "../../../actions/cShift/reducer.actions";
|
} from "../../../actions/cShift/reducer.actions";
|
||||||
|
import { createMultipleCShiftRequest } from "../../../actions/cShift/saga.actions";
|
||||||
|
import Error from "../../Shared/Error";
|
||||||
|
|
||||||
import "react-datepicker/dist/react-datepicker.css";
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
import "./shiftStartTimeOverrides.css";
|
import "./shiftStartTimeOverrides.css";
|
||||||
|
@ -41,7 +44,7 @@ for (let min = 60; min <= 480; min += 30) {
|
||||||
|
|
||||||
class ClientAddShiftForm extends Component {
|
class ClientAddShiftForm extends Component {
|
||||||
componentWillMount = () => {
|
componentWillMount = () => {
|
||||||
this.props.dispatch(setClearCshiftState());
|
this.props.dispatch(setClearCShiftState());
|
||||||
};
|
};
|
||||||
|
|
||||||
changeSelectedEmployee = (e, { value }) => {
|
changeSelectedEmployee = (e, { value }) => {
|
||||||
|
@ -86,8 +89,36 @@ class ClientAddShiftForm extends Component {
|
||||||
this.props.dispatch(setFormShiftDates(shiftDatesCopy));
|
this.props.dispatch(setFormShiftDates(shiftDatesCopy));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onSubmitShifts = event => {
|
||||||
|
event.preventDefault();
|
||||||
|
// change this into interable cshift post request bodies
|
||||||
|
const { priceUUID, startTime, duration, note, shiftDates } = this.props;
|
||||||
|
const postRequestBodies = [];
|
||||||
|
for (let shiftDateString in shiftDates) {
|
||||||
|
const dynamicStartTime = utc(startTime);
|
||||||
|
const startDate = shiftDates[shiftDateString];
|
||||||
|
dynamicStartTime.set({
|
||||||
|
year: startDate.get("year"),
|
||||||
|
month: startDate.get("month"),
|
||||||
|
date: startDate.get("date")
|
||||||
|
});
|
||||||
|
const dynamicEndTime = utc(dynamicStartTime);
|
||||||
|
dynamicEndTime.add(duration, "minutes");
|
||||||
|
postRequestBodies.push({
|
||||||
|
get_price_uuid: priceUUID,
|
||||||
|
set_start: dynamicStartTime.format(),
|
||||||
|
set_end: dynamicEndTime.format(),
|
||||||
|
description: note ? note : undefined
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.props.dispatch(createMultipleCShiftRequest(postRequestBodies));
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
|
isSendingCShiftRequest,
|
||||||
|
cShiftRequestErrors,
|
||||||
|
cShiftRequestSuccess,
|
||||||
selfUser,
|
selfUser,
|
||||||
employeeUUID,
|
employeeUUID,
|
||||||
priceUUID,
|
priceUUID,
|
||||||
|
@ -101,6 +132,10 @@ class ClientAddShiftForm extends Component {
|
||||||
return <Redirect to="/" />;
|
return <Redirect to="/" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cShiftRequestSuccess) {
|
||||||
|
console.log(cShiftRequestSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
const employeeChoices = selfUser.client.employees
|
const employeeChoices = selfUser.client.employees
|
||||||
.filter(employee => !employee.deleted && !!employee.approved)
|
.filter(employee => !employee.deleted && !!employee.approved)
|
||||||
.map(({ uuid, provider }) => ({
|
.map(({ uuid, provider }) => ({
|
||||||
|
@ -120,7 +155,7 @@ class ClientAddShiftForm extends Component {
|
||||||
.map(({ amount, uuid, work_type }) => ({
|
.map(({ amount, uuid, work_type }) => ({
|
||||||
key: uuid,
|
key: uuid,
|
||||||
value: uuid,
|
value: uuid,
|
||||||
text: work_type.label,
|
text: `${work_type.label} ($${amount}/hr)`,
|
||||||
content: (
|
content: (
|
||||||
<Header>
|
<Header>
|
||||||
<Label
|
<Label
|
||||||
|
@ -147,6 +182,9 @@ class ClientAddShiftForm extends Component {
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<ClientAddShiftFormView
|
<ClientAddShiftFormView
|
||||||
|
isSendingCShiftRequest={isSendingCShiftRequest}
|
||||||
|
cShiftRequestErrors={cShiftRequestErrors}
|
||||||
|
cShiftRequestSuccess={!!cShiftRequestSuccess.length}
|
||||||
user={selfUser}
|
user={selfUser}
|
||||||
employeeChoices={employeeChoices}
|
employeeChoices={employeeChoices}
|
||||||
priceChoices={priceChoices}
|
priceChoices={priceChoices}
|
||||||
|
@ -162,6 +200,7 @@ class ClientAddShiftForm extends Component {
|
||||||
changeShiftDuration={this.changeShiftDuration}
|
changeShiftDuration={this.changeShiftDuration}
|
||||||
changeShiftNote={this.changeShiftNote}
|
changeShiftNote={this.changeShiftNote}
|
||||||
handleSelectDate={this.handleSelectDate}
|
handleSelectDate={this.handleSelectDate}
|
||||||
|
onSubmitShifts={this.onSubmitShifts}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -172,6 +211,9 @@ function mapStateToProps(state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ClientAddShiftFormView = ({
|
const ClientAddShiftFormView = ({
|
||||||
|
isSendingCShiftRequest,
|
||||||
|
cShiftRequestErrors,
|
||||||
|
cShiftRequestSuccess,
|
||||||
user,
|
user,
|
||||||
employeeChoices,
|
employeeChoices,
|
||||||
priceChoices,
|
priceChoices,
|
||||||
|
@ -186,11 +228,17 @@ const ClientAddShiftFormView = ({
|
||||||
changeShiftStartTime,
|
changeShiftStartTime,
|
||||||
changeShiftDuration,
|
changeShiftDuration,
|
||||||
changeShiftNote,
|
changeShiftNote,
|
||||||
handleSelectDate
|
handleSelectDate,
|
||||||
|
onSubmitShifts
|
||||||
}) => (
|
}) => (
|
||||||
<Container>
|
<Container>
|
||||||
<Header>Schedule Shifts</Header>
|
<Header>Schedule Shifts</Header>
|
||||||
<Form>
|
<Form
|
||||||
|
loading={isSendingCShiftRequest}
|
||||||
|
onSubmit={onSubmitShifts}
|
||||||
|
error={!!cShiftRequestErrors.length}
|
||||||
|
success={!!cShiftRequestSuccess}
|
||||||
|
>
|
||||||
<Form.Group widths="equal">
|
<Form.Group widths="equal">
|
||||||
<Form.Field>
|
<Form.Field>
|
||||||
<label>Employee</label>
|
<label>Employee</label>
|
||||||
|
@ -214,6 +262,7 @@ const ClientAddShiftFormView = ({
|
||||||
selection
|
selection
|
||||||
fluid
|
fluid
|
||||||
search
|
search
|
||||||
|
disabled={!employeeUUID}
|
||||||
noResultsMessage="No prices for given employee."
|
noResultsMessage="No prices for given employee."
|
||||||
value={priceUUID}
|
value={priceUUID}
|
||||||
/>
|
/>
|
||||||
|
@ -266,6 +315,16 @@ const ClientAddShiftFormView = ({
|
||||||
.endOf("month")}
|
.endOf("month")}
|
||||||
/>
|
/>
|
||||||
</Form.Field>
|
</Form.Field>
|
||||||
|
{!!cShiftRequestErrors.length && (
|
||||||
|
<Error header="" error={cShiftRequestErrors[0]} />
|
||||||
|
)}
|
||||||
|
<Message success>
|
||||||
|
<Message.Header>Add Shift successful!</Message.Header>
|
||||||
|
<p>Shifts successfully scheduled.</p>
|
||||||
|
{!!cShiftRequestSuccess && (
|
||||||
|
<Redirect to="/user/profile/client/shifts" />
|
||||||
|
)}
|
||||||
|
</Message>
|
||||||
<Form.Button>Schedule Shift</Form.Button>
|
<Form.Button>Schedule Shift</Form.Button>
|
||||||
</Form>
|
</Form>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Reducer CShift Action Constants
|
// Reducer CShift Action Constants
|
||||||
export const IS_SENDING_CSHIFT_REQUEST = "IS_SENDING_CSHIFT_REQUEST";
|
export const IS_SENDING_CSHIFT_REQUEST = "IS_SENDING_CSHIFT_REQUEST";
|
||||||
export const SET_CSHIFT_REQUEST_ERROR = "SET_CSHIFT_REQUEST_ERROR";
|
export const SET_CSHIFT_REQUEST_ERRORS = "SET_CSHIFT_REQUEST_ERRORS";
|
||||||
export const CLEAR_CSHIFT_REQUEST_ERROR = "CLEAR_CSHIFT_REQUEST_ERROR";
|
export const CLEAR_CSHIFT_REQUEST_ERRORS = "CLEAR_CSHIFT_REQUEST_ERRORS";
|
||||||
export const SET_CSHIFT_REQUEST_SUCCESS = "SET_CSHIFT_REQUEST_SUCCESS";
|
export const SET_CSHIFT_REQUEST_SUCCESS = "SET_CSHIFT_REQUEST_SUCCESS";
|
||||||
export const CLEAR_CSHIFT_REQUEST_SUCCESS = "CLEAR_CSHIFT_REQUEST_SUCCESS";
|
export const CLEAR_CSHIFT_REQUEST_SUCCESS = "CLEAR_CSHIFT_REQUEST_SUCCESS";
|
||||||
export const SET_FORM_EMPLOYEE_UUID = "SET_FORM_EMPLOYEE_UUID";
|
export const SET_FORM_EMPLOYEE_UUID = "SET_FORM_EMPLOYEE_UUID";
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {
|
import {
|
||||||
IS_SENDING_CSHIFT_REQUEST,
|
IS_SENDING_CSHIFT_REQUEST,
|
||||||
SET_CSHIFT_REQUEST_ERROR,
|
SET_CSHIFT_REQUEST_ERRORS,
|
||||||
CLEAR_CSHIFT_REQUEST_ERROR,
|
CLEAR_CSHIFT_REQUEST_ERRORS,
|
||||||
SET_CSHIFT_REQUEST_SUCCESS,
|
SET_CSHIFT_REQUEST_SUCCESS,
|
||||||
CLEAR_CSHIFT_REQUEST_SUCCESS,
|
CLEAR_CSHIFT_REQUEST_SUCCESS,
|
||||||
SET_FORM_EMPLOYEE_UUID,
|
SET_FORM_EMPLOYEE_UUID,
|
||||||
|
@ -15,7 +15,7 @@ import {
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
isSendingCShiftRequest: false,
|
isSendingCShiftRequest: false,
|
||||||
cShiftRequestError: "",
|
cShiftRequestErrors: [],
|
||||||
cShiftRequestSuccess: "",
|
cShiftRequestSuccess: "",
|
||||||
employeeUUID: "", // Which employee
|
employeeUUID: "", // Which employee
|
||||||
priceUUID: "", // Which price
|
priceUUID: "", // Which price
|
||||||
|
@ -32,15 +32,15 @@ function cShiftReducer(state = initialState, action) {
|
||||||
...state,
|
...state,
|
||||||
isSendingCShiftRequest: action.data
|
isSendingCShiftRequest: action.data
|
||||||
};
|
};
|
||||||
case SET_CSHIFT_REQUEST_ERROR:
|
case SET_CSHIFT_REQUEST_ERRORS:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
cShiftRequestError: action.data
|
cShiftRequestErrors: action.data
|
||||||
};
|
};
|
||||||
case CLEAR_CSHIFT_REQUEST_ERROR:
|
case CLEAR_CSHIFT_REQUEST_ERRORS:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
cShiftRequestError: ""
|
cShiftRequestErrors: []
|
||||||
};
|
};
|
||||||
case SET_CSHIFT_REQUEST_SUCCESS:
|
case SET_CSHIFT_REQUEST_SUCCESS:
|
||||||
return {
|
return {
|
||||||
|
|
61
src/sagas/cShift.sagas.js
Normal file
61
src/sagas/cShift.sagas.js
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
import { effects } from "redux-saga";
|
||||||
|
import {
|
||||||
|
isSendingCShiftRequest,
|
||||||
|
setCShiftRequestError,
|
||||||
|
setCShiftRequestErrors,
|
||||||
|
setCShiftRequestSuccess,
|
||||||
|
clearCShiftRequestError,
|
||||||
|
clearCShiftRequestSuccess,
|
||||||
|
setFormEmployeeUUID,
|
||||||
|
setFormPriceUUID,
|
||||||
|
setFormShiftDates,
|
||||||
|
setFormShiftDuration,
|
||||||
|
setFormShiftNote,
|
||||||
|
setFormShiftStartTime
|
||||||
|
} from "../actions/cShift/reducer.actions";
|
||||||
|
import { createCShifts } from "../api/cShift.api";
|
||||||
|
|
||||||
|
function* createCShiftsCall(postBodies) {
|
||||||
|
yield effects.put(isSendingCShiftRequest(true));
|
||||||
|
try {
|
||||||
|
if (postBodies.length > 0) {
|
||||||
|
return yield effects.call(createCShifts, postBodies);
|
||||||
|
} else {
|
||||||
|
yield effects.put(
|
||||||
|
setCShiftRequestError({
|
||||||
|
response: { data: { dates: ["No dates selected."] } }
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (exception) {
|
||||||
|
yield effects.put(setCShiftRequestError(exception));
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
yield effects.put(isSendingCShiftRequest(false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* createCShiftsFlow(request) {
|
||||||
|
yield effects.put(clearCShiftRequestSuccess());
|
||||||
|
yield effects.put(clearCShiftRequestError());
|
||||||
|
const arrResponses = yield effects.call(createCShiftsCall, request.data);
|
||||||
|
console.log(arrResponses);
|
||||||
|
if (arrResponses) {
|
||||||
|
const errorResps = arrResponses.filter(resp => !!resp.error);
|
||||||
|
if (errorResps.length > 0) {
|
||||||
|
console.log(arrResponses);
|
||||||
|
yield effects.put(setCShiftRequestErrors(errorResps));
|
||||||
|
}
|
||||||
|
const succResps = arrResponses.filter(resp => !resp.error);
|
||||||
|
if (succResps.length > 0) {
|
||||||
|
yield effects.put(setCShiftRequestSuccess(succResps));
|
||||||
|
yield effects.put(setFormEmployeeUUID(""));
|
||||||
|
yield effects.put(setFormPriceUUID(""));
|
||||||
|
yield effects.put(setFormShiftStartTime(null));
|
||||||
|
yield effects.put(setFormShiftDuration(""));
|
||||||
|
yield effects.put(setFormShiftNote(""));
|
||||||
|
yield effects.put(setFormShiftDates({}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -69,6 +69,8 @@ import {
|
||||||
updatePriceFlow,
|
updatePriceFlow,
|
||||||
deletePriceFlow
|
deletePriceFlow
|
||||||
} from "./price.sagas";
|
} from "./price.sagas";
|
||||||
|
import { CREATE_MULTIPLE_CSHIFT_REQUEST } from "../constants/cShift.constants";
|
||||||
|
import { createCShiftsFlow } from "./cShift.sagas";
|
||||||
|
|
||||||
export default function* rootSaga() {
|
export default function* rootSaga() {
|
||||||
yield takeLatest(SEND_REGISTER_REQUEST, registerUserFlow);
|
yield takeLatest(SEND_REGISTER_REQUEST, registerUserFlow);
|
||||||
|
@ -96,4 +98,5 @@ export default function* rootSaga() {
|
||||||
yield takeLatest(CREATE_PRICE_REQUEST, createPriceFlow);
|
yield takeLatest(CREATE_PRICE_REQUEST, createPriceFlow);
|
||||||
yield takeLatest(UPDATE_PRICE_REQUEST, updatePriceFlow);
|
yield takeLatest(UPDATE_PRICE_REQUEST, updatePriceFlow);
|
||||||
yield takeLatest(DELETE_PRICE_REQUEST, deletePriceFlow);
|
yield takeLatest(DELETE_PRICE_REQUEST, deletePriceFlow);
|
||||||
|
yield takeLatest(CREATE_MULTIPLE_CSHIFT_REQUEST, createCShiftsFlow);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user