I'm building a profile page for users of my app (nextjs 12) and when I add authentication middleware it works fine locally but when deployed to the production server (apache shared hosting with nodejs v 14 installed) it throws error 500
my node version installed locally is v16.16.0 could that affect this issue?
any suggestions?
profile.tsx:
const ProfileEditor = () => {
const dispatch = useDispatch();
const {
profile,
profileLogin,
user
} = useSelector((state: RootState) => state.Auth);
useEffect(() => {
dispatch(FetchProfileAsync());
}, []);
const [preview, setPreview] = useState < string > ();
const handleFormSubmit = async(values: any, e: any) => {
dispatch(UpdateProfileAsync(values as any));
};
let initialValues = {
image: profile ? .image ? .full_path,
first_name: profile ? .first_name,
last_name: profile ? .last_name,
email: profile ? .email,
phone: profile ? .phone,
};
const FILE_SIZE = 160 * 1024;
const SUPPORTED_FORMATS = ['image/jpg', 'image/png'];
const checkoutSchema = yup.object().shape({
image: yup.mixed().required('A file is required'),
// .test('fileSize', 'File too large', (value) => value && value.size <= FILE_SIZE)
// .test('fileFormat', 'Unsupported Format', (value) => value && SUPPORTED_FORMATS.includes(value.type)),
first_name: yup.string().required('required'),
last_name: yup.string().required('required'),
email: yup.string().email('invalid email').required('required'),
phone: yup.string().required('required'),
});
return ( <
CustomerDashboardLayout >
<
DashboardPageHeader icon = {
Person
}
title = 'Edit Profile'
navigation = { < CustomerDashboardNavigation / >
}
/>
<
Card1 >
<
Formik enableReinitialize initialValues = {
initialValues
}
validationSchema = {
checkoutSchema
}
onSubmit = {
(values: any, e: any) => handleFormSubmit(values, e)
} >
{
({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
setFieldValue
}) => ( <
form onSubmit = {
handleSubmit
} >
<
FlexBox alignItems = 'flex-end'
mb = {
3
} >
<
Avatar src = {
preview ? ? user ? .image ? .full_path
}
sx = {
{
height: 64,
width: 64
}
}
alt = 'user image' / >
{ /* <img src={user?.image?.full_path} height={100} width={100} alt='fdss' /> */ }
<
Box ml = {-2.5
} >
<
label htmlFor = 'profile-image' >
<
Button component = 'span'
color = 'secondary'
sx = {
{
bgcolor: 'grey.300',
height: 'auto',
p: '8px',
borderRadius: '50%',
}
} >
<
CameraEnhance fontSize = 'small' / >
<
/Button> <
/label> <
/Box> <
Box display = 'none' >
<
input name = 'image'
onChange = {
(newFile: any) => {
setFieldValue('image', newFile.currentTarget.files[0]);
FileToBase64(newFile.currentTarget.files[0] as any).then((res) => setPreview(res));
}
}
id = 'profile-image'
accept = 'image/*'
type = 'file' /
>
<
/Box> <
/FlexBox>
<
Box mb = {
4
} >
<
Grid container spacing = {
3
} >
<
Grid item md = {
6
}
xs = {
12
} >
<
ETextField mb = {
1.5
}
name = 'first_name'
label = 'First Name'
placeholder = 'First Name'
variant = 'outlined'
size = 'small'
fullWidth onBlur = {
handleBlur
}
onChange = {
handleChange
}
value = {
values.first_name || ''
}
error = {!!touched.first_name && !!errors.first_name
}
helperText = {
touched.first_name && errors.first_name
}
/> <
/Grid> <
Grid item md = {
6
}
xs = {
12
} >
<
ETextField mb = {
1.5
}
name = 'last_name'
label = 'Last Name'
placeholder = 'Last Name'
variant = 'outlined'
size = 'small'
fullWidth onBlur = {
handleBlur
}
onChange = {
handleChange
}
value = {
values.last_name || ''
}
error = {!!touched.last_name && !!errors.last_name
}
helperText = {
touched.last_name && errors.last_name
}
/> <
/Grid> <
Grid item md = {
6
}
xs = {
12
} >
<
ETextField mb = {
1.5
}
name = 'email'
label = 'Email'
placeholder = 'exmple#mail.com'
variant = 'outlined'
size = 'small'
type = 'email'
fullWidth onBlur = {
handleBlur
}
onChange = {
handleChange
}
value = {
values.email || ''
}
error = {!!touched.email && !!errors.email
}
helperText = {
touched.email && errors.email
}
/> <
/Grid> <
Grid item md = {
6
}
xs = {
12
} >
<
ETextField mb = {
1.5
}
name = 'phone'
label = 'Phone'
placeholder = '09********'
variant = 'outlined'
size = 'small'
fullWidth onBlur = {
handleBlur
}
onChange = {
handleChange
}
value = {
values.phone || ''
}
error = {!!touched.phone && !!errors.phone
}
helperText = {
touched.phone && errors.phone
}
/> <
/Grid> <
/Grid> <
/Box>
<
ELoadingButton type = 'submit'
variant = 'contained'
loading = {
profileLogin === 'loading'
}
buttonText = 'Save Changes'
loadingPosition = 'start'
fullWidth = {
true
}
color = 'primary' /
>
<
/form>
)
} <
/Formik> <
/Card1> <
/CustomerDashboardLayout>
);
};
export default ProfileEditor;
middlware.tsx
// eslint-disable-next-line #next/next/no-server-import-in-page
import { NextResponse } from 'next/server';
// eslint-disable-next-line #next/next/no-server-import-in-page
import type { NextRequest } from 'next/server';
import { KEY_TOKEN_COOKIE } from 'src/constants';
const middleware = (request: NextRequest, response: NextResponse) => {
const token = request?.cookies[KEY_TOKEN_COOKIE];
if (!token) return NextResponse.rewrite(new URL('/error/auth', request.url));
};
export default middleware;
Related
NumericFormat is used with MUI TextField and prefix prop. When I start writing any number, I cannot write more than one number. If I write fast this time I can write all numbers but the prefix is gone.
All numbers inserted from the keyboard should be shown, and shouldn't be any missing numbers at the start the prefix should be visible but this is not working.
import { Observer } from "mobx-react-lite";
import { TextField, TextFieldProps } from "#mui/material";
import { AllowedNames } from "../utils/utils";
import { useDialogState } from "../states/dialog-state";
import { NumericFormat, NumericFormatProps } from "react-number-format";
import React from "react";
interface NumericFormatCustomProps {
onChange: (event: { target: { name: string; value: string } }) => void;
name: string;
}
const NumericFormatCustom = React.forwardRef<
NumericFormatProps<HTMLInputElement>,
NumericFormatCustomProps & NumericFormatProps<HTMLInputElement>
>(function NumericFormatCustom(props, ref) {
const { onChange, prefix, suffix, ...other } = props;
return (
<NumericFormat
{...other}
getInputRef={ref}
onValueChange={(values) => {
onChange({
target: {
name: props.name,
value: values.value,
},
});
}}
prefix={prefix}
suffix={suffix}
/>
);
});
function getValue(value: any, coefficient: number) {
if (value === "" || value === null || value === undefined) {
return "";
}
return ((value ?? 0) / Math.pow(10, coefficient)).toString();
}
function setValue(value: any, coefficient: number, decimalPlaces: number) {
if (value === "" || value === null || value === undefined) {
return null;
}
return (
(Math.round(parseFloat(value) * Math.pow(10, decimalPlaces)) /
Math.pow(10, decimalPlaces)) *
Math.pow(10, coefficient)
);
}
export type FormNumberFieldProps<T extends object> = Omit<
TextFieldProps,
"defaultValue" | "type"
> & {
dataKey: AllowedNames<T, number>;
prefix?: string;
suffix?: string;
decimalPlaces?: number;
coefficient?: number;
thousandSeparator?: boolean;
min?: number;
max?: number;
};
export default function FormNumberField<T extends object>({
dataKey,
prefix = "$ ",
suffix = "",
decimalPlaces = 0,
coefficient = 0,
thousandSeparator = true,
min,
max,
...rest
}: FormNumberFieldProps<T>) {
const [internalError, setInternalError] = React.useState("");
const stateProvider = useDialogState<T>();
const state = stateProvider.state;
return (
<Observer>
{() => {
const value = getValue(state.getValue(dataKey) as any, coefficient);
const checkMinMax = () => {
const numberValue = parseInt(value, 10);
if (typeof min === "number") {
if (numberValue < min) {
setInternalError(`The value should be more than ${min}`);
return;
}
}
if (typeof max === "number") {
if (numberValue > max) {
setInternalError(`The value should be less than ${max}`);
return;
}
}
setInternalError("");
};
return (
<TextField
{...rest}
fullWidth
inputMode="numeric"
onBlur={checkMinMax}
value={value}
onChange={(e) => {
state.setValue(
dataKey,
setValue(e.target.value, coefficient, decimalPlaces) as any,
);
}}
error={!!internalError || !!state.errorOf(dataKey)}
helperText={internalError || state.errorOf(dataKey)}
InputLabelProps={{ shrink: true }}
InputProps={{
inputComponent: NumericFormatCustom as any,
inputProps: {
prefix,
suffix,
thousandSeparator,
},
}}
/>
);
}}
</Observer>
);
}
import { Observer } from "mobx-react-lite";
import { TextField, TextFieldProps } from "#mui/material";
import { AllowedNames } from "../utils/utils";
import { useDialogState } from "../states/dialog-state";
import { NumericFormat, NumericFormatProps } from "react-number-format";
import React from "react";
interface NumericFormatCustomProps {
onChange: (event: { target: { name: string; value: string } }) => void;
name: string;
}
const NumericFormatCustom = React.forwardRef<
NumericFormatProps<HTMLInputElement>,
NumericFormatCustomProps & NumericFormatProps<HTMLInputElement>
>(function NumericFormatCustom(props, ref) {
const { onChange, prefix, suffix, ...other } = props;
return (
<NumericFormat
{...other}
getInputRef={ref}
onValueChange={(values) => {
onChange({
target: {
name: props.name,
value: values.value,
},
});
}}
prefix={prefix}
suffix={suffix}
/>
);
});
function getValue(value: any, coefficient: number) {
if (value === "" || value === null || value === undefined) {
return "";
}
return ((value ?? 0) / Math.pow(10, coefficient)).toString();
}
function setValue(value: any, coefficient: number, decimalPlaces: number) {
if (value === "" || value === null || value === undefined) {
return null;
}
return (
(Math.round(parseFloat(value) * Math.pow(10, decimalPlaces)) /
Math.pow(10, decimalPlaces)) *
Math.pow(10, coefficient)
);
}
export type FormNumberFieldProps<T extends object> = Omit<
TextFieldProps,
"defaultValue" | "type"
> & {
dataKey: AllowedNames<T, number>;
prefix?: string;
suffix?: string;
decimalPlaces?: number;
coefficient?: number;
thousandSeparator?: boolean;
min?: number;
max?: number;
};
export default function FormNumberField<T extends object>({
dataKey,
prefix = "$ ",
suffix = "",
decimalPlaces = 0,
coefficient = 0,
thousandSeparator = true,
min,
max,
...rest
}: FormNumberFieldProps<T>) {
const [internalError, setInternalError] = React.useState("");
const stateProvider = useDialogState<T>();
const state = stateProvider.state;
// I moved here
const value = getValue(state.getValue(dataKey) as any, coefficient);
return (
<Observer>
{() => {
const checkMinMax = () => {
const numberValue = parseInt(value, 10);
if (typeof min === "number") {
if (numberValue < min) {
setInternalError(`The value should be more than ${min}`);
return;
}
}
if (typeof max === "number") {
if (numberValue > max) {
setInternalError(`The value should be less than ${max}`);
return;
}
}
setInternalError("");
};
return (
<TextField
{...rest}
fullWidth
inputMode="numeric"
onBlur={checkMinMax}
value={value}
onChange={(e) => {
state.setValue(
dataKey,
setValue(e.target.value, coefficient, decimalPlaces) as any,
);
}}
error={!!internalError || !!state.errorOf(dataKey)}
helperText={internalError || state.errorOf(dataKey)}
InputLabelProps={{ shrink: true }}
InputProps={{
inputComponent: NumericFormatCustom as any,
inputProps: {
prefix,
suffix,
thousandSeparator,
},
}}
/>
);
}}
</Observer>
);
}
When testing the API I have noticed that it is getting called around 6 times, there is no for/foreach loop that would make it run several times in the code so am unsure as to why this may be happening.
The API runs every time a user goes onto the Landing Screen.
Any advice would be appreciated
exports.getFilteredOpportunities = async (req, res) => {
let mongoQuery = generateMongoQuery(req);
try {
const opps = await Opportunity.find(mongoQuery)
.select(removeItems)
.sort({
createdAt: -1
});
res.status(200).json({
opportunities: opps,
});
} catch (error) {
res.status(500).json({
status: "error",
message: error,
});
}
};
GenerateMongoQuery function
const generateMongoQuery = (req) => {
let query = {};
// search param used searching through Title field, ie. search=food
if (req.query.search && req.query.search.length > 0) {
query.$or = [{}, {}];
query.$or[0].Title = query.$or[1].Description = new RegExp(
`${req.query.search}`,
"i"
);
}
// location param, i.e location=Glasgow,Manchester
if (req.query.location && req.query.location.length > 0) {
query.location = {
$in: req.query.location.split(",")
};
}
// timeslot param, i.e timeslot=Evening,Morning
if (req.query.timeslot && req.query.timeslot.length > 0) {
query.timeslot = {
$in: req.query.timeslot.split(",")
};
}
// category param, returning corresponding id i.e category=
if (req.query.category && req.query.category.length > 0) {
query.category = {
$in: req.query.category.split(",")
};
}
// Dont load expired opportunities
query.eventDate = {
$gte: new Date().toDateString()
};
// Only return non-cancelled opportunities
query.isCancelled = false;
return query;
};
The landing Screen
import { useState, useEffect } from "react";
import Opportunities from "../components/molecules/Opportunities";
import Filters from "../components/organisms/Filters";
import { IOpportunity } from "../Models/IOpportunity";
import OpportunitiesClient from "../Api/opportunitiesClient";
import Utils from "../Utils/Utils";
import FiltersClient from "../Api/filtersClient";
import { IFilters } from "../Models/IFilters";
import { ISelectedFilters } from "../Models/ISelectedFilters";
import Header from "../components/atoms/Header";
import Footer from "../components/atoms/Footer";
export default function LandingScreen(props) {
const [opportunities, setOpportunities] = useState<IOpportunity[]>([]);
const [filters, setFilters] = useState<IFilters[]>([]);
const [checkedFilters, setCheckedFilters] = useState<
ISelectedFilters | undefined
>({
Location: [],
Category: [],
Timeslot: [],
});
const [isLoading, setLoading] = useState<boolean>(true);
const [allResultsLoaded, setAllResultsLoaded] = useState<boolean>(false);
let pageToGet = 1;
const [scrollPosition, setScrollPosition] = useState(0);
const [totalOpps, setTotalOpps] = useState(0);
useEffect(() => {
getOpportunities();
getFilters();
}, []);
useEffect(() => {
setTotalOpps(opportunities.length);
}, [opportunities]);
const handleScroll = () => {
setScrollPosition(window.pageYOffset);
let scrollHeight = 0;
if ((props.scrollHeight === null) !== undefined) {
scrollHeight = +props.scrollHeight;
} else {
scrollHeight = document.scrollingElement.scrollHeight;
}
if (
window.innerHeight + document.documentElement.scrollTop >=
scrollHeight
) {
if (allResultsLoaded === false) {
setLoading(true);
}
setTimeout(() => {
pageToGet += 1;
getOpportunities();
}, 600);
}
window.removeEventListener("scroll", handleScroll);
};
window.addEventListener("scroll", handleScroll, { passive: true });
const setItemChecked = (filtername: string, filterType: string) => {
// reset page and results
pageToGet = 1;
setAllResultsLoaded(false);
setCheckedFilters(
Utils.setItemChecked(filtername, filterType, checkedFilters)
);
};
const resetFilters = () => {
// reset page and results
pageToGet = 1;
setAllResultsLoaded(false);
checkedFilters.Location = [];
checkedFilters.Category = [];
checkedFilters.Timeslot = [];
getOpportunities();
};
const getFilters = () => {
FiltersClient.getAll().then((filters) => {
setFilters(filters);
});
};
const getOpportunities = () => {
console.log(opportunities);
OpportunitiesClient.getWithParams(
Utils.getAxiosParams(checkedFilters)
).then((res) => {
definePage(res);
if (opportunities.length === res["opportunities"].length)
setAllResultsLoaded(true);
setLoading(false);
});
};
const definePage = (res) => {
if (pageToGet === 1) {
setOpportunities(res["opportunities"].slice(0, 15));
} else {
setOpportunities(
opportunities.concat(
res["opportunities"].slice(
opportunities.length,
opportunities.length + 15
)
)
);
}
};
return (
<div>
<Header page="landing" includePostButton={true} />
<div
data-testid="test-div1"
className="grid md:grid-cols-[150px_auto] sm:grid-cols-1 md:grid-flow-col gap-4 mx-4 mb-5 my-10"
>
<div></div>
<div className="card-container-title">
{totalOpps} Results{" "}
{checkedFilters.Location.length > 0 ? "(Filtered)" : ""}
</div>
</div>
<div
data-testid="test-div3"
className="grid md:grid-cols-[150px_auto] sm:grid-cols-1 md:grid-flow-col gap-4 mx-4"
>
<div>
<Filters
filters={filters}
getChecked={setItemChecked}
urlCall={getOpportunities}
resetFilters={resetFilters}
checkedFilters={checkedFilters}
/>
</div>
<div
data-testid="test-div4"
className={isLoading ? "opacity-50" : ""}
>
<div className="col-span-2">
<Opportunities
items={opportunities}
isLoading={isLoading}
allResultsLoaded={allResultsLoaded}
/>
</div>
</div>
</div>
<Footer />
</div>
);
}
I'm trying to generate more than one thousand pdf files using surveyPDF.
The problem is that i can generate only 80 pdf files...
I'm passing an array with more than 1000 pdf to generate.
Code :
query.map(async items => {
const { generatePdf } = await import("~/lib/survey");
const filename = kebabCase(
`${campaign.title} - ${items.employee.fullName.toLowerCase()} -${moment().format("DD/MM/YYYY - HH:mm")} `
);
return generatePdf(campaign.template.body, items, filename, 210, 297);
});
The code which generate each pdfs :
import autoTable from "jspdf-autotable";
import { SurveyPDF, CommentBrick, CompositeBrick, PdfBrick, TextBrick } from "survey-pdf";
import { format } from "~/utils/date";
class AutoTableBrick extends PdfBrick {
constructor(question, controller, rect, options) {
super(question, controller, rect);
this.margins = {
top: controller.margins.top,
bottom: controller.margins.bot,
right: 30,
left: 30,
};
this.options = options;
}
renderInteractive() {
if (this.controller.doc.lastAutoTable && !this.options.isFirstQuestion) {
this.options.startY = this.yTop;
}
autoTable(this.controller.doc, {
head: [
[
{
content: this.question.title,
colSpan: 2,
styles: { fillColor: "#5b9bd5" },
},
],
],
margin: { ...this.margins },
styles: { fillColor: "#fff", lineWidth: 1, lineColor: "#5b9bd5", minCellWidth: 190 },
alternateRowStyles: { fillColor: "#bdd6ee" },
...this.options,
});
}
}
export async function generatePdf(json, data, filename, pdfWidth, pdfHeight) {
if (!json) {
return Promise.reject("Invalid json for pdf export");
}
for (const page of json.pages) {
page.readOnly = true;
}
const surveyPDF = new SurveyPDF(json, {
fontSize: 11,
format: [pdfWidth, pdfHeight],
commercial: true,
textFieldRenderAs: "multiLine",
});
surveyPDF.showQuestionNumbers = "off";
surveyPDF.storeOthersAsComment = false;
//TODO This does not work well with dynamic dropdown, bug declared
// surveyPDF.mode = "display";
surveyPDF.mergeData({ ...data, _: {} });
surveyPDF.onRenderQuestion.add(function(survey, options) {
const { bricks, question } = options;
if (question.getType() === "comment" && question.value && bricks.length > 0) {
for (const brick of bricks) {
if (brick.value) {
brick.value = question.value.replace(/\t/g, " ");
}
if (brick instanceof CompositeBrick) {
const { bricks } = brick;
for (const brick of bricks) {
if (brick instanceof CommentBrick) {
brick.value = question.value.replace(/\t/g, " ");
}
}
}
}
}
});
surveyPDF.onRenderQuestion.add(async function(survey, options) {
const {
point,
bricks,
question,
controller,
module: { SurveyHelper },
} = options;
if (question.getType() === "multipletext") {
const body = [];
let extraRows = 0;
let rows = question.getRows();
for (let i = 0; i < rows.length; i++) {
for (let j = 0; j < rows[i].length; j++) {
let { title, value, inputType } = rows[i][j];
if (inputType === "date") {
value = format(value);
}
if (typeof value === "string" && value.length > 0) {
const valueEstRows = value.match(/.{1,70}/g).length;
if (valueEstRows > 1) {
extraRows += valueEstRows;
}
}
body.push([title, value || "N/A"]);
}
}
//TODO Use SurveyHelper helperDoc do calculate the height of the auto table
const startY = point.yTop;
const height = 21.5 * (body.length + 1) + 8.5 * extraRows;
const isFirstQuestion = question.title === question.parent.questions[0].title;
options.bricks = [
new AutoTableBrick(question, controller, SurveyHelper.createRect(point, bricks[0].width, height), {
startY,
body,
isFirstQuestion,
}),
];
}
});
surveyPDF.onRenderQuestion.add(async function(survey, options) {
const {
point,
question,
controller,
module: { SurveyHelper },
} = options;
if (question.getType() === "text") {
//Draw question background
const { default: backImage } = await import("~/public/assets/images/block.png");
const backWidth = SurveyHelper.getPageAvailableWidth(controller);
const backHeight = SurveyHelper.pxToPt(100);
const imageBackBrick = SurveyHelper.createImageFlat(point, null, controller, backImage, backWidth, backHeight);
options.bricks = [imageBackBrick];
point.xLeft += controller.unitWidth;
point.yTop += controller.unitHeight;
const oldFontSize = controller.fontSize;
const titleBrick = await SurveyHelper.createTitleFlat(point, question, controller);
controller.fontSize = oldFontSize;
titleBrick.unfold()[0]["textColor"] = "#6a6772";
options.bricks.push(titleBrick);
//Draw text question text field border
let { default: textFieldImage } = await import("~/public/assets/images/input.png");
let textFieldPoint = SurveyHelper.createPoint(imageBackBrick);
textFieldPoint.xLeft += controller.unitWidth;
textFieldPoint.yTop -= controller.unitHeight * 3.3;
let textFieldWidth = imageBackBrick.width - controller.unitWidth * 2;
let textFieldHeight = controller.unitHeight * 2;
let imageTextFieldBrick = SurveyHelper.createImageFlat(
textFieldPoint,
null,
controller,
textFieldImage,
textFieldWidth,
textFieldHeight
);
options.bricks.push(imageTextFieldBrick);
textFieldPoint.xLeft += controller.unitWidth / 2;
textFieldPoint.yTop += controller.unitHeight / 2;
let textFieldValue = question.value || "";
if (textFieldValue.length > 90) {
textFieldValue = textFieldValue.substring(0, 95) + "...";
}
const textFieldBrick = await SurveyHelper.createBoldTextFlat(
textFieldPoint,
question,
controller,
textFieldValue
);
controller.fontSize = oldFontSize;
textFieldBrick.unfold()[0]["textColor"] = "#EFF8FF";
options.bricks.push(textFieldBrick);
}
});
surveyPDF.onRenderQuestion.add(async function(survey, options) {
const {
point,
question,
controller,
module: { SurveyHelper },
} = options;
if (question.getType() === "radiogroup" || question.getType() === "rating") {
options.bricks = [];
const oldFontSize = controller.fontSize;
const titleLocation = question.hasTitle ? question.getTitleLocation() : "hidden";
let fieldPoint;
if (["hidden", "matrix"].includes(titleLocation)) {
fieldPoint = SurveyHelper.clone(point);
} else {
const titleBrick = await SurveyHelper.createTitleFlat(point, question, controller);
titleBrick.xLeft += controller.unitWidth;
titleBrick.yTop += controller.unitHeight * 2;
controller.fontSize = oldFontSize;
titleBrick.unfold()[0]["textColor"] = "#6a6772";
options.bricks.push(titleBrick);
fieldPoint = SurveyHelper.createPoint(titleBrick);
fieldPoint.yTop += controller.unitHeight * 1.3;
}
//Draw checkbox question items field
const { default: itemEmptyImage } = await import("~/public/assets/images/unchecked.png");
const { default: itemFilledImage } = await import("~/public/assets/images/checked.png");
const itemSide = controller.unitWidth;
let imageItemBrick;
const choices = question.getType() === "rating" ? question.visibleRateValues : question.visibleChoices;
for (const choice of choices) {
const isItemSelected =
question.getType() === "rating" ? question.value === choice.value : choice === question.selectedItem;
imageItemBrick = SurveyHelper.createImageFlat(
fieldPoint,
null,
controller,
isItemSelected ? itemFilledImage : itemEmptyImage,
itemSide,
itemSide
);
options.bricks.push(imageItemBrick);
const textPoint = SurveyHelper.clone(fieldPoint);
textPoint.xLeft += itemSide + controller.unitWidth / 2;
textPoint.yTop += itemSide / 12;
const itemValue = choice.locText.renderedHtml;
const checkboxTextBrick = await SurveyHelper.createTextFlat(
textPoint,
question,
controller,
itemValue,
TextBrick
);
checkboxTextBrick.unfold()[0]["textColor"] = "#6a6772";
fieldPoint.yTop = imageItemBrick.yBot + SurveyHelper.GAP_BETWEEN_ROWS * controller.unitHeight;
options.bricks.push(checkboxTextBrick);
}
}
});
surveyPDF.onRenderFooter.add(function(survey, canvas) {
canvas.drawText({
text: canvas.pageNumber + "/" + canvas.countPages,
fontSize: 10,
horizontalAlign: "right",
margins: {
right: 12,
},
});
});
return await surveyPDF.raw(`./pdf/${filename}.pdf`);
}
The error :
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
I have already try to increase the node memory using $env:NODE_OPTIONS="--max-old-space-size=8192"
I have been working on a project to generate configurable dashboards.
so i have to generate schema dynamically based on an api request. is there any way to do that?
it will be very helpful if there is any working example!
There's an asyncModule function for this scenario. You can check example below:
const fetch = require('node-fetch');
const Funnels = require('Funnels');
asyncModule(async () => {
const funnels = await (await fetch('http://your-api-endpoint/funnels')).json();
class Funnel {
constructor({ title, steps }) {
this.title = title;
this.steps = steps;
}
get transformedSteps() {
return Object.keys(this.steps).map((key, index) => {
const value = this.steps[key];
let where = null
if (value[0] === PAGE_VIEW_EVENT) {
if (value.length === 1) {
where = `event = '${value[0]}'`
} else {
where = `event = '${value[0]}' AND page_title = '${value[1]}'`
}
} else {
where = `event = 'se' AND se_category = '${value[0]}' AND se_action = '${value[1]}'`
}
return {
name: key,
eventsView: {
sql: () => `select * from (${eventsSQl}) WHERE ${where}`
},
timeToConvert: index > 0 ? '30 day' : null
}
});
}
get config() {
return {
userId: {
sql: () => `user_id`
},
time: {
sql: () => `time`
},
steps: this.transformedSteps
}
}
}
funnels.forEach((funnel) => {
const funnelObject = new Funnel(funnel);
cube(funnelObject.title, {
extends: Funnels.eventFunnel(funnelObject.config),
preAggregations: {
main: {
type: `originalSql`,
}
}
});
});
})
More info: https://cube.dev/docs/schema-execution-environment#async-module
i am new in react native,i try to developing native application in react native but i have onPress click event issue.
InfoSwipper.js file i was click on Sign In button display "undefined is not an object(evaluating 'this.props.navigator.push') ". I am not sure what I am missing. please some one help me.
Thank you in advance.
index.android.js file code
"use strict";
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Navigator,
StatusBar,
AsyncStorage,
} from 'react-native';
var SignUp = require("./components/SignUp");
var InfoScreens = require("./components/InfoScreens");
import SplashScreen from 'react-native-splash-screen'
var Kahaani = React.createClass({
_renderScene(route, navigator) {
if (route.id === 0) {
return <InfoScreens navigator={navigator} />
}
else if (route.id === 1) {
StatusBar.setHidden(false);
console.log('WRONG SIGNIN', "here");
return <LogIn navigator={navigator} />
}
},
componentDidMount() {
// do anything while splash screen keeps, use await to wait for an async task.
SplashScreen.hide();
},
render: function() {
return (
<Navigator
style={styles.navigationContainer}
initialRoute={{id: 0, }}
renderScene={this._renderScene} />
);
}
});
var styles = StyleSheet.create({
navigationContainer: {
flex: 1,
},
});
AppRegistry.registerComponent('Kahaani', () => Kahaani);
swipperScreen.js
'use strict';
import React, { Component } from 'react';
import {
Dimensions, // Detects screen dimensions
Platform, // Detects platform running the app
ScrollView, // Handles navigation between screens
StyleSheet, // CSS-like styles
View,
Text,Navigator, TouchableHighlight, // Container component
} from 'react-native';
import LogIn from './LogIn';
var navigator;
class InfoScreenSwiper extends Component {
constructor(props)
{
super(props);
}
static defaultProps = {
horizontal: true,
pagingEnabled: true,
showsHorizontalScrollIndicator: false,
showsVerticalScrollIndicator: false,
bounces: false,
scrollsToTop: false,
removeClippedSubviews: true,
automaticallyAdjustContentInsets: false,
index: 0
};
state = this.initState(this.props);
initState(props) {
const total = props.children ? props.children.length || 1 : 0,
index = total > 1 ? Math.min(props.index, total - 1) : 0,
offset = width * index;
const state = {
total,
index,
offset,
width,
height,
};
this.internals = {
isScrolling: false,
offset
};
return state;
}
onScrollBegin = e => {
// Update internal isScrolling state
this.internals.isScrolling = true;
}
onScrollEnd = e => {
// Update internal isScrolling state
this.internals.isScrolling = false;
// Update index
this.updateIndex(e.nativeEvent.contentOffset
? e.nativeEvent.contentOffset.x
// When scrolled with .scrollTo() on Android there is no contentOffset
: e.nativeEvent.position * this.state.width
);
}
onScrollEndDrag = e => {
const { contentOffset: { x: newOffset } } = e.nativeEvent,
{ children } = this.props,
{ index } = this.state,
{ offset } = this.internals;
if (offset === newOffset &&
(index === 0 || index === children.length - 1)) {
this.internals.isScrolling = false;
}
}
updateIndex = (offset) => {
const state = this.state,
diff = offset - this.internals.offset,
step = state.width;
let index = state.index;
if (!diff) {
return;
}
index = parseInt(index + Math.round(diff / step), 10);
this.internals.offset = offset;
this.setState({
index
});
}
swipe = () => {
if (this.internals.isScrolling || this.state.total < 2) {
return;
}
const state = this.state,
diff = this.state.index + 1,
x = diff * state.width,
y = 0;
this.scrollView && this.scrollView.scrollTo({ x, y, animated: true });
this.internals.isScrolling = true;
if (Platform.OS === 'android') {
setImmediate(() => {
this.onScrollEnd({
nativeEvent: {
position: diff
}
});
});
}
}
renderScrollView = pages => {
return (
<ScrollView ref={component => { this.scrollView = component; }}
{...this.props}
contentContainerStyle={[styles.wrapper, this.props.style]}
onScrollBeginDrag={this.onScrollBegin}
onMomentumScrollEnd={this.onScrollEnd}
onScrollEndDrag={this.onScrollEndDrag}
>
{pages.map((page, i) =>
// Render each slide inside a View
<View style={[styles.fullScreen, styles.slide]} key={i}>
{page}
</View>
)}
</ScrollView>
);
}
renderPagination = () => {
if (this.state.total <= 1) {
return null;
}
const ActiveDot = <View style={[styles.dot, styles.activeDot]} />,
Dot = <View style={styles.dot} />;
let dots = [];
for (let key = 0; key < this.state.total; key++) {
dots.push(key === this.state.index
// Active dot
? React.cloneElement(ActiveDot, { key })
// Other dots
: React.cloneElement(Dot, { key })
);
}
return (
<View
pointerEvents="none"
style={[styles.pagination, styles.fullScreen]}>
{dots}
</View>
);
}
onMainPressLogIn= () =>
{
console.log('WRONG SIGNIN', "onMainPressLogIn");
this.props.navigator.push({
id:1
});
}
onSubmitPressed () {
console.log('WRONG SIGNIN', "onSubmitPressed");
this.props.navigator.push({
id:2
})
}
renderButtonBottom = () => {
const lastScreen = this.state.index === this.state.total - 1;
return (
<View pointerEvents="box-none" style={[styles.buttonWrapper]}>
<View style={ [styles.viewButton]}>
<Text style={[styles.buttonLogIn,styles.buttonAll]} onPress={this.onMainPressLogIn} >LOG IN</Text>
<Text style={[styles.buttonSignUp,styles.buttonAll]} onPress={(this.onSubmitPressed.bind(this))}>SIGN UP</Text>
</View>
</View>
);
}
render = ({ children } = this.props) => {
return (
<View style={[styles.container, styles.fullScreen]}>
{/* Render screens */}
{this.renderScrollView(children)}
{/* Render pagination */}
{this.renderPagination()}
{/* Render Continue or Done button */}
{this.renderButtonBottom()}
</View>
);
}
}
module.exports = InfoScreenSwiper;