mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-11 02:39:02 +08:00
Feature(FE): signup page (#642)
* chore: icon is updated * feat: signup page design is updated * chore: set get user pref is added * chore: svg is added * feat: signup page is updated * feat: signup page is updated
This commit is contained in:
parent
be8ec756c6
commit
1ee2e302e2
9
frontend/public/signoz-signup.svg
Normal file
9
frontend/public/signoz-signup.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 10 KiB |
@ -2,4 +2,4 @@
|
|||||||
<path d="M765.131 338.922L805.631 334.984C808.068 348.578 812.99 358.562 820.396 364.938C827.896 371.312 837.974 374.5 850.631 374.5C864.037 374.5 874.115 371.688 880.865 366.062C887.709 360.344 891.131 353.688 891.131 346.094C891.131 341.219 889.677 337.094 886.771 333.719C883.959 330.25 878.99 327.25 871.865 324.719C866.99 323.031 855.881 320.031 838.537 315.719C816.224 310.188 800.568 303.391 791.568 295.328C778.912 283.984 772.584 270.156 772.584 253.844C772.584 243.344 775.537 233.547 781.443 224.453C787.443 215.266 796.021 208.281 807.177 203.5C818.427 198.719 831.974 196.328 847.818 196.328C873.693 196.328 893.146 202 906.177 213.344C919.302 224.688 926.193 239.828 926.849 258.766L885.224 260.594C883.443 250 879.599 242.406 873.693 237.812C867.881 233.125 859.115 230.781 847.396 230.781C835.302 230.781 825.834 233.266 818.99 238.234C814.584 241.422 812.381 245.688 812.381 251.031C812.381 255.906 814.443 260.078 818.568 263.547C823.818 267.953 836.568 272.547 856.818 277.328C877.068 282.109 892.021 287.078 901.677 292.234C911.427 297.297 919.021 304.281 924.459 313.188C929.99 322 932.756 332.922 932.756 345.953C932.756 357.766 929.474 368.828 922.912 379.141C916.349 389.453 907.068 397.141 895.068 402.203C883.068 407.172 868.115 409.656 850.209 409.656C824.146 409.656 804.131 403.656 790.162 391.656C776.193 379.562 767.849 361.984 765.131 338.922ZM967.49 236.406V199.844H1007.01V236.406H967.49ZM967.49 406V256.656H1007.01V406H967.49ZM1043.99 415.844L1089.13 421.328C1089.88 426.578 1091.61 430.188 1094.33 432.156C1098.08 434.969 1103.99 436.375 1112.05 436.375C1122.36 436.375 1130.1 434.828 1135.26 431.734C1138.72 429.672 1141.35 426.344 1143.13 421.75C1144.35 418.469 1144.96 412.422 1144.96 403.609V381.812C1133.15 397.938 1118.24 406 1100.24 406C1080.18 406 1064.29 397.516 1052.57 380.547C1043.38 367.141 1038.79 350.453 1038.79 330.484C1038.79 305.453 1044.79 286.328 1056.79 273.109C1068.88 259.891 1083.88 253.281 1101.79 253.281C1120.26 253.281 1135.49 261.391 1147.49 277.609V256.656H1184.47V390.672C1184.47 408.297 1183.02 421.469 1180.11 430.188C1177.21 438.906 1173.13 445.75 1167.88 450.719C1162.63 455.688 1155.6 459.578 1146.79 462.391C1138.07 465.203 1127.01 466.609 1113.6 466.609C1088.29 466.609 1070.33 462.25 1059.74 453.531C1049.15 444.906 1043.85 433.938 1043.85 420.625C1043.85 419.312 1043.9 417.719 1043.99 415.844ZM1079.29 328.234C1079.29 344.078 1082.33 355.703 1088.43 363.109C1094.61 370.422 1102.21 374.078 1111.21 374.078C1120.86 374.078 1129.02 370.328 1135.68 362.828C1142.33 355.234 1145.66 344.031 1145.66 329.219C1145.66 313.75 1142.47 302.266 1136.1 294.766C1129.72 287.266 1121.66 283.516 1111.91 283.516C1102.44 283.516 1094.61 287.219 1088.43 294.625C1082.33 301.938 1079.29 313.141 1079.29 328.234ZM1224.41 406V199.844H1264.91L1349.29 337.516V199.844H1387.96V406H1346.19L1263.08 271.562V406H1224.41ZM1422.69 329.219C1422.69 316.094 1425.93 303.391 1432.4 291.109C1438.86 278.828 1448.01 269.453 1459.82 262.984C1471.72 256.516 1484.99 253.281 1499.61 253.281C1522.21 253.281 1540.72 260.641 1555.16 275.359C1569.6 289.984 1576.82 308.5 1576.82 330.906C1576.82 353.5 1569.51 372.25 1554.88 387.156C1540.35 401.969 1522.02 409.375 1499.9 409.375C1486.21 409.375 1473.13 406.281 1460.66 400.094C1448.29 393.906 1438.86 384.859 1432.4 372.953C1425.93 360.953 1422.69 346.375 1422.69 329.219ZM1463.19 331.328C1463.19 346.141 1466.71 357.484 1473.74 365.359C1480.77 373.234 1489.44 377.172 1499.76 377.172C1510.07 377.172 1518.69 373.234 1525.63 365.359C1532.66 357.484 1536.18 346.047 1536.18 331.047C1536.18 316.422 1532.66 305.172 1525.63 297.297C1518.69 289.422 1510.07 285.484 1499.76 285.484C1489.44 285.484 1480.77 289.422 1473.74 297.297C1466.71 305.172 1463.19 316.516 1463.19 331.328ZM1592.01 406V375.203L1647.97 310.938C1657.16 300.438 1663.96 292.984 1668.36 288.578C1663.77 288.859 1657.72 289.047 1650.22 289.141L1597.49 289.422V256.656H1720.96V284.641L1663.86 350.453L1643.76 372.25C1654.72 371.594 1661.52 371.266 1664.15 371.266H1725.32V406H1592.01Z" fill="white"/>
|
<path d="M765.131 338.922L805.631 334.984C808.068 348.578 812.99 358.562 820.396 364.938C827.896 371.312 837.974 374.5 850.631 374.5C864.037 374.5 874.115 371.688 880.865 366.062C887.709 360.344 891.131 353.688 891.131 346.094C891.131 341.219 889.677 337.094 886.771 333.719C883.959 330.25 878.99 327.25 871.865 324.719C866.99 323.031 855.881 320.031 838.537 315.719C816.224 310.188 800.568 303.391 791.568 295.328C778.912 283.984 772.584 270.156 772.584 253.844C772.584 243.344 775.537 233.547 781.443 224.453C787.443 215.266 796.021 208.281 807.177 203.5C818.427 198.719 831.974 196.328 847.818 196.328C873.693 196.328 893.146 202 906.177 213.344C919.302 224.688 926.193 239.828 926.849 258.766L885.224 260.594C883.443 250 879.599 242.406 873.693 237.812C867.881 233.125 859.115 230.781 847.396 230.781C835.302 230.781 825.834 233.266 818.99 238.234C814.584 241.422 812.381 245.688 812.381 251.031C812.381 255.906 814.443 260.078 818.568 263.547C823.818 267.953 836.568 272.547 856.818 277.328C877.068 282.109 892.021 287.078 901.677 292.234C911.427 297.297 919.021 304.281 924.459 313.188C929.99 322 932.756 332.922 932.756 345.953C932.756 357.766 929.474 368.828 922.912 379.141C916.349 389.453 907.068 397.141 895.068 402.203C883.068 407.172 868.115 409.656 850.209 409.656C824.146 409.656 804.131 403.656 790.162 391.656C776.193 379.562 767.849 361.984 765.131 338.922ZM967.49 236.406V199.844H1007.01V236.406H967.49ZM967.49 406V256.656H1007.01V406H967.49ZM1043.99 415.844L1089.13 421.328C1089.88 426.578 1091.61 430.188 1094.33 432.156C1098.08 434.969 1103.99 436.375 1112.05 436.375C1122.36 436.375 1130.1 434.828 1135.26 431.734C1138.72 429.672 1141.35 426.344 1143.13 421.75C1144.35 418.469 1144.96 412.422 1144.96 403.609V381.812C1133.15 397.938 1118.24 406 1100.24 406C1080.18 406 1064.29 397.516 1052.57 380.547C1043.38 367.141 1038.79 350.453 1038.79 330.484C1038.79 305.453 1044.79 286.328 1056.79 273.109C1068.88 259.891 1083.88 253.281 1101.79 253.281C1120.26 253.281 1135.49 261.391 1147.49 277.609V256.656H1184.47V390.672C1184.47 408.297 1183.02 421.469 1180.11 430.188C1177.21 438.906 1173.13 445.75 1167.88 450.719C1162.63 455.688 1155.6 459.578 1146.79 462.391C1138.07 465.203 1127.01 466.609 1113.6 466.609C1088.29 466.609 1070.33 462.25 1059.74 453.531C1049.15 444.906 1043.85 433.938 1043.85 420.625C1043.85 419.312 1043.9 417.719 1043.99 415.844ZM1079.29 328.234C1079.29 344.078 1082.33 355.703 1088.43 363.109C1094.61 370.422 1102.21 374.078 1111.21 374.078C1120.86 374.078 1129.02 370.328 1135.68 362.828C1142.33 355.234 1145.66 344.031 1145.66 329.219C1145.66 313.75 1142.47 302.266 1136.1 294.766C1129.72 287.266 1121.66 283.516 1111.91 283.516C1102.44 283.516 1094.61 287.219 1088.43 294.625C1082.33 301.938 1079.29 313.141 1079.29 328.234ZM1224.41 406V199.844H1264.91L1349.29 337.516V199.844H1387.96V406H1346.19L1263.08 271.562V406H1224.41ZM1422.69 329.219C1422.69 316.094 1425.93 303.391 1432.4 291.109C1438.86 278.828 1448.01 269.453 1459.82 262.984C1471.72 256.516 1484.99 253.281 1499.61 253.281C1522.21 253.281 1540.72 260.641 1555.16 275.359C1569.6 289.984 1576.82 308.5 1576.82 330.906C1576.82 353.5 1569.51 372.25 1554.88 387.156C1540.35 401.969 1522.02 409.375 1499.9 409.375C1486.21 409.375 1473.13 406.281 1460.66 400.094C1448.29 393.906 1438.86 384.859 1432.4 372.953C1425.93 360.953 1422.69 346.375 1422.69 329.219ZM1463.19 331.328C1463.19 346.141 1466.71 357.484 1473.74 365.359C1480.77 373.234 1489.44 377.172 1499.76 377.172C1510.07 377.172 1518.69 373.234 1525.63 365.359C1532.66 357.484 1536.18 346.047 1536.18 331.047C1536.18 316.422 1532.66 305.172 1525.63 297.297C1518.69 289.422 1510.07 285.484 1499.76 285.484C1489.44 285.484 1480.77 289.422 1473.74 297.297C1466.71 305.172 1463.19 316.516 1463.19 331.328ZM1592.01 406V375.203L1647.97 310.938C1657.16 300.438 1663.96 292.984 1668.36 288.578C1663.77 288.859 1657.72 289.047 1650.22 289.141L1597.49 289.422V256.656H1720.96V284.641L1663.86 350.453L1643.76 372.25C1654.72 371.594 1661.52 371.266 1664.15 371.266H1725.32V406H1592.01Z" fill="white"/>
|
||||||
<path opacity="0.9" d="M296.795 599.499C131.909 599.499 0 468.361 0 304.437C0 142.153 131.909 9.37476 296.795 9.37476H483.116C544.124 9.37476 591.941 58.5518 591.941 117.564V304.437C591.941 468.361 460.032 599.499 296.795 599.499Z" fill="#F25733"/>
|
<path opacity="0.9" d="M296.795 599.499C131.909 599.499 0 468.361 0 304.437C0 142.153 131.909 9.37476 296.795 9.37476H483.116C544.124 9.37476 591.941 58.5518 591.941 117.564V304.437C591.941 468.361 460.032 599.499 296.795 599.499Z" fill="#F25733"/>
|
||||||
<path d="M294.467 176.702C171.309 176.702 101.936 280.076 99.0428 284.476C91.91 295.315 91.91 309.334 99.0481 320.181C101.936 324.574 171.309 427.947 294.467 427.947C417.624 427.947 486.997 324.574 489.89 320.173C497.023 309.334 497.024 295.315 489.885 284.468C486.997 280.076 417.624 176.702 294.467 176.702ZM116.09 308.659C113.557 304.811 113.557 299.839 116.09 295.99C118.416 292.45 167.808 218.911 256.115 201.271C216.099 216.928 187.625 256.307 187.625 302.325C187.625 348.342 216.099 387.721 256.115 403.378C167.808 385.737 118.416 312.198 116.09 308.659ZM245.232 302.324C245.232 308.059 240.646 312.706 234.989 312.706C229.331 312.706 224.746 308.059 224.746 302.324C224.746 263.357 256.022 231.655 294.466 231.655C300.123 231.655 304.709 236.303 304.709 242.037C304.709 247.772 300.123 252.419 294.466 252.419C267.317 252.419 245.232 274.806 245.232 302.324ZM294.467 327.565C280.736 327.565 269.565 316.243 269.565 302.325C269.565 288.407 280.736 277.084 294.467 277.084C308.199 277.084 319.369 288.406 319.369 302.325C319.369 316.243 308.199 327.565 294.467 327.565ZM472.843 308.659C470.516 312.198 421.125 385.737 332.818 403.378C372.836 387.72 401.309 348.342 401.309 302.325C401.309 256.307 372.836 216.929 332.818 201.272C421.125 218.913 470.516 292.451 472.843 295.99C475.376 299.839 475.376 304.811 472.843 308.659Z" fill="#F9F2F9"/>
|
<path d="M294.467 176.702C171.309 176.702 101.936 280.076 99.0428 284.476C91.91 295.315 91.91 309.334 99.0481 320.181C101.936 324.574 171.309 427.947 294.467 427.947C417.624 427.947 486.997 324.574 489.89 320.173C497.023 309.334 497.024 295.315 489.885 284.468C486.997 280.076 417.624 176.702 294.467 176.702ZM116.09 308.659C113.557 304.811 113.557 299.839 116.09 295.99C118.416 292.45 167.808 218.911 256.115 201.271C216.099 216.928 187.625 256.307 187.625 302.325C187.625 348.342 216.099 387.721 256.115 403.378C167.808 385.737 118.416 312.198 116.09 308.659ZM245.232 302.324C245.232 308.059 240.646 312.706 234.989 312.706C229.331 312.706 224.746 308.059 224.746 302.324C224.746 263.357 256.022 231.655 294.466 231.655C300.123 231.655 304.709 236.303 304.709 242.037C304.709 247.772 300.123 252.419 294.466 252.419C267.317 252.419 245.232 274.806 245.232 302.324ZM294.467 327.565C280.736 327.565 269.565 316.243 269.565 302.325C269.565 288.407 280.736 277.084 294.467 277.084C308.199 277.084 319.369 288.406 319.369 302.325C319.369 316.243 308.199 327.565 294.467 327.565ZM472.843 308.659C470.516 312.198 421.125 385.737 332.818 403.378C372.836 387.72 401.309 348.342 401.309 302.325C401.309 256.307 372.836 216.929 332.818 201.272C421.125 218.913 470.516 292.451 472.843 295.99C475.376 299.839 475.376 304.811 472.843 308.659Z" fill="#F9F2F9"/>
|
||||||
</svg>
|
</svg>
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
24
frontend/src/api/user/getPreference.ts
Normal file
24
frontend/src/api/user/getPreference.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import axios from 'api';
|
||||||
|
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||||
|
import { AxiosError } from 'axios';
|
||||||
|
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||||
|
import { PayloadProps } from 'types/api/user/getUserPreference';
|
||||||
|
|
||||||
|
const getPreference = async (): Promise<
|
||||||
|
SuccessResponse<PayloadProps> | ErrorResponse
|
||||||
|
> => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`/userPreferences`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusCode: 200,
|
||||||
|
error: null,
|
||||||
|
message: response.data.status,
|
||||||
|
payload: response.data,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return ErrorResponseHandler(error as AxiosError);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getPreference;
|
24
frontend/src/api/user/getVersion.ts
Normal file
24
frontend/src/api/user/getVersion.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import axios from 'api';
|
||||||
|
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||||
|
import { AxiosError } from 'axios';
|
||||||
|
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||||
|
import { PayloadProps } from 'types/api/user/getVersion';
|
||||||
|
|
||||||
|
const getVersion = async (): Promise<
|
||||||
|
SuccessResponse<PayloadProps> | ErrorResponse
|
||||||
|
> => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`/version`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusCode: 200,
|
||||||
|
error: null,
|
||||||
|
message: response.data.status,
|
||||||
|
payload: response.data,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return ErrorResponseHandler(error as AxiosError);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getVersion;
|
26
frontend/src/api/user/setPreference.ts
Normal file
26
frontend/src/api/user/setPreference.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import axios from 'api';
|
||||||
|
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||||
|
import { AxiosError } from 'axios';
|
||||||
|
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||||
|
import { PayloadProps, Props } from 'types/api/user/setUserPreference';
|
||||||
|
|
||||||
|
const setPreference = async (
|
||||||
|
props: Props,
|
||||||
|
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`/userPreferences`, {
|
||||||
|
...props,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusCode: 200,
|
||||||
|
error: null,
|
||||||
|
message: response.data.status,
|
||||||
|
payload: response.data,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return ErrorResponseHandler(error as AxiosError);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default setPreference;
|
@ -9,8 +9,7 @@ const signup = async (
|
|||||||
): Promise<SuccessResponse<undefined> | ErrorResponse> => {
|
): Promise<SuccessResponse<undefined> | ErrorResponse> => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(`/user`, {
|
const response = await axios.post(`/user`, {
|
||||||
email: props.email,
|
...props,
|
||||||
name: props.name,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
219
frontend/src/pages/SignUp/SignUp.tsx
Normal file
219
frontend/src/pages/SignUp/SignUp.tsx
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Input,
|
||||||
|
notification,
|
||||||
|
Typography,
|
||||||
|
Switch,
|
||||||
|
Space,
|
||||||
|
Card,
|
||||||
|
} from 'antd';
|
||||||
|
import signup from 'api/user/signup';
|
||||||
|
import ROUTES from 'constants/routes';
|
||||||
|
import history from 'lib/history';
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import setLocalStorageKey from 'api/browser/localstorage/set';
|
||||||
|
|
||||||
|
import AppActions from 'types/actions';
|
||||||
|
const { Title } = Typography;
|
||||||
|
import { PayloadProps } from 'types/api/user/getUserPreference';
|
||||||
|
|
||||||
|
import {
|
||||||
|
ButtonContainer,
|
||||||
|
Container,
|
||||||
|
FormWrapper,
|
||||||
|
Label,
|
||||||
|
LeftContainer,
|
||||||
|
Logo,
|
||||||
|
MarginTop,
|
||||||
|
} from './styles';
|
||||||
|
import { IS_LOGGED_IN } from 'constants/auth';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { Dispatch } from 'redux';
|
||||||
|
import setPreference from 'api/user/setPreference';
|
||||||
|
|
||||||
|
const Signup = ({ version, userpref }: SignupProps): JSX.Element => {
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const [firstName, setFirstName] = useState<string>('');
|
||||||
|
const [email, setEmail] = useState<string>('');
|
||||||
|
const [organizationName, setOrganisationName] = useState<string>('');
|
||||||
|
const [hasOptedUpdates, setHasOptedUpdates] = useState<boolean>(
|
||||||
|
userpref.hasOptedUpdates,
|
||||||
|
);
|
||||||
|
const [isAnonymous, setisAnonymous] = useState<boolean>(userpref.isAnonymous);
|
||||||
|
|
||||||
|
const dispatch = useDispatch<Dispatch<AppActions>>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setisAnonymous(userpref.isAnonymous);
|
||||||
|
setHasOptedUpdates(userpref.hasOptedUpdates);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const setState = (
|
||||||
|
value: string,
|
||||||
|
setFunction: React.Dispatch<React.SetStateAction<string>>,
|
||||||
|
) => {
|
||||||
|
setFunction(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = (e: React.FormEvent<HTMLFormElement>): void => {
|
||||||
|
(async (): Promise<void> => {
|
||||||
|
try {
|
||||||
|
e.preventDefault();
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
const userPrefernceResponse = await setPreference({
|
||||||
|
isAnonymous,
|
||||||
|
hasOptedUpdates,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (userPrefernceResponse.statusCode === 200) {
|
||||||
|
const response = await signup({
|
||||||
|
email: email,
|
||||||
|
name: firstName,
|
||||||
|
organizationName,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.statusCode === 200) {
|
||||||
|
setLocalStorageKey(IS_LOGGED_IN, 'yes');
|
||||||
|
dispatch({
|
||||||
|
type: 'LOGGED_IN',
|
||||||
|
});
|
||||||
|
|
||||||
|
history.push(ROUTES.APPLICATION);
|
||||||
|
} else {
|
||||||
|
notification.error({
|
||||||
|
message: 'Something went wrong',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
notification.error({
|
||||||
|
message: 'Something went wrong',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
|
} catch (error) {
|
||||||
|
notification.error({
|
||||||
|
message: 'Something went wrong',
|
||||||
|
});
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(userpref);
|
||||||
|
|
||||||
|
const onSwitchHandler = (
|
||||||
|
value: boolean,
|
||||||
|
setFunction: React.Dispatch<React.SetStateAction<boolean>>,
|
||||||
|
) => {
|
||||||
|
setFunction(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<LeftContainer direction="vertical">
|
||||||
|
<Space align="center">
|
||||||
|
<Logo src={'signoz-signup.svg'} alt="logo" />
|
||||||
|
<Title style={{ fontSize: '46px', margin: 0 }}>SigNoz</Title>
|
||||||
|
</Space>
|
||||||
|
<Typography>
|
||||||
|
Monitor your applications. Find what is causing issues.
|
||||||
|
</Typography>
|
||||||
|
<Card
|
||||||
|
style={{ width: 'max-content' }}
|
||||||
|
bodyStyle={{ padding: '1px 8px', width: '100%' }}
|
||||||
|
>
|
||||||
|
SigNoz {version}
|
||||||
|
</Card>
|
||||||
|
</LeftContainer>
|
||||||
|
|
||||||
|
<FormWrapper>
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<Title level={4}>Create your account</Title>
|
||||||
|
<div>
|
||||||
|
<Label htmlFor="signupEmail">Email</Label>
|
||||||
|
<Input
|
||||||
|
placeholder="mike@netflix.com"
|
||||||
|
type="email"
|
||||||
|
autoFocus
|
||||||
|
value={email}
|
||||||
|
onChange={(e): void => {
|
||||||
|
setState(e.target.value, setEmail);
|
||||||
|
}}
|
||||||
|
required
|
||||||
|
id="signupEmail"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Label htmlFor="signupFirstName">First Name</Label>
|
||||||
|
<Input
|
||||||
|
placeholder="Mike"
|
||||||
|
value={firstName}
|
||||||
|
onChange={(e): void => {
|
||||||
|
setState(e.target.value, setFirstName);
|
||||||
|
}}
|
||||||
|
required
|
||||||
|
id="signupFirstName"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label htmlFor="organizationName">Organization Name</Label>
|
||||||
|
<Input
|
||||||
|
placeholder="Netflix"
|
||||||
|
value={organizationName}
|
||||||
|
onChange={(e): void => {
|
||||||
|
setState(e.target.value, setOrganisationName);
|
||||||
|
}}
|
||||||
|
required
|
||||||
|
id="organizationName"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<MarginTop marginTop={'2.4375rem'}>
|
||||||
|
<Space>
|
||||||
|
<Switch
|
||||||
|
onChange={(value) => onSwitchHandler(value, setHasOptedUpdates)}
|
||||||
|
checked={hasOptedUpdates}
|
||||||
|
/>
|
||||||
|
<Typography>Keep me updated on new SigNoz features</Typography>
|
||||||
|
</Space>
|
||||||
|
</MarginTop>
|
||||||
|
|
||||||
|
<MarginTop marginTop={'0.5rem'}>
|
||||||
|
<Space>
|
||||||
|
<Switch
|
||||||
|
onChange={(value) => onSwitchHandler(value, setisAnonymous)}
|
||||||
|
checked={isAnonymous}
|
||||||
|
/>
|
||||||
|
<Typography>
|
||||||
|
Anonymise my usage date. We collect data to measure product usage
|
||||||
|
</Typography>
|
||||||
|
</Space>
|
||||||
|
</MarginTop>
|
||||||
|
|
||||||
|
<ButtonContainer>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
htmlType="submit"
|
||||||
|
data-attr="signup"
|
||||||
|
loading={loading}
|
||||||
|
disabled={loading || !email || !organizationName || !firstName}
|
||||||
|
>
|
||||||
|
Get Started
|
||||||
|
</Button>
|
||||||
|
</ButtonContainer>
|
||||||
|
</form>
|
||||||
|
</FormWrapper>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
interface SignupProps {
|
||||||
|
version: string;
|
||||||
|
userpref: PayloadProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Signup;
|
@ -1,148 +1,43 @@
|
|||||||
import { Button, Input, notification, Typography } from 'antd';
|
import useFetch from 'hooks/useFetch';
|
||||||
import signup from 'api/user/signup';
|
import React from 'react';
|
||||||
import ROUTES from 'constants/routes';
|
import SignUpComponent from './SignUp';
|
||||||
import history from 'lib/history';
|
import getVersion from 'api/user/getVersion';
|
||||||
import React, { useState } from 'react';
|
import { PayloadProps as VersionPayload } from 'types/api/user/getVersion';
|
||||||
import { connect } from 'react-redux';
|
import { PayloadProps as UserPrefPayload } from 'types/api/user/getUserPreference';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { ThunkDispatch } from 'redux-thunk';
|
|
||||||
import { UserLoggedIn } from 'store/actions';
|
|
||||||
import AppActions from 'types/actions';
|
|
||||||
|
|
||||||
import {
|
import Spinner from 'components/Spinner';
|
||||||
ButtonContainer,
|
import { Typography } from 'antd';
|
||||||
Container,
|
import getPreference from 'api/user/getPreference';
|
||||||
FormWrapper,
|
|
||||||
LogoImageContainer,
|
|
||||||
Title,
|
|
||||||
} from './styles';
|
|
||||||
|
|
||||||
const Signup = ({ loggedIn }: SignupProps): JSX.Element => {
|
const SignUp = () => {
|
||||||
const [notificationsInstance, Element] = notification.useNotification();
|
const versionResponse = useFetch<VersionPayload, undefined>(getVersion);
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const userPrefResponse = useFetch<UserPrefPayload, undefined>(getPreference);
|
||||||
|
|
||||||
const [formState, setFormState] = useState({
|
if (versionResponse.error || userPrefResponse.error) {
|
||||||
firstName: { value: '' },
|
return (
|
||||||
email: { value: '' },
|
<Typography>
|
||||||
});
|
{versionResponse.errorMessage ||
|
||||||
|
userPrefResponse.errorMessage ||
|
||||||
|
'Somehthing went wrong'}
|
||||||
|
</Typography>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const updateForm = (
|
if (
|
||||||
name: string,
|
versionResponse.loading ||
|
||||||
target: EventTarget & HTMLInputElement,
|
versionResponse.payload === undefined ||
|
||||||
): void => {
|
userPrefResponse.loading ||
|
||||||
if (name === 'firstName') {
|
userPrefResponse.payload === undefined
|
||||||
setFormState({
|
) {
|
||||||
...formState,
|
return <Spinner tip="Loading.." />;
|
||||||
firstName: { ...formState.firstName, value: target.value },
|
}
|
||||||
});
|
|
||||||
} else if (name === 'email') {
|
|
||||||
setFormState({
|
|
||||||
...formState,
|
|
||||||
email: { ...formState.email, value: target.value },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent<HTMLFormElement>): void => {
|
const version = versionResponse.payload.version;
|
||||||
(async (): Promise<void> => {
|
|
||||||
try {
|
|
||||||
e.preventDefault();
|
|
||||||
setLoading(true);
|
|
||||||
const payload = {
|
|
||||||
first_name: formState.firstName,
|
|
||||||
email: formState.email,
|
|
||||||
};
|
|
||||||
|
|
||||||
const response = await signup({
|
const userpref = userPrefResponse.payload;
|
||||||
email: payload.email.value,
|
|
||||||
name: payload.first_name.value,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.statusCode === 200) {
|
return <SignUpComponent userpref={userpref} version={version} />;
|
||||||
loggedIn();
|
|
||||||
history.push(ROUTES.APPLICATION);
|
|
||||||
} else {
|
|
||||||
notificationsInstance.error({
|
|
||||||
message: 'Something went wrong',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setLoading(false);
|
|
||||||
} catch (error) {
|
|
||||||
notificationsInstance.error({
|
|
||||||
message: 'Something went wrong',
|
|
||||||
});
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
{Element}
|
|
||||||
|
|
||||||
<Container direction="vertical">
|
|
||||||
<Title>Create your account</Title>
|
|
||||||
<Typography>
|
|
||||||
Monitor your applications. Find what is causing issues.
|
|
||||||
</Typography>
|
|
||||||
</Container>
|
|
||||||
|
|
||||||
<FormWrapper>
|
|
||||||
<LogoImageContainer src={'signoz.svg'} alt="logo" />
|
|
||||||
|
|
||||||
<form onSubmit={handleSubmit}>
|
|
||||||
<div>
|
|
||||||
<label htmlFor="signupEmail">Email</label>
|
|
||||||
<Input
|
|
||||||
placeholder="mike@netflix.com"
|
|
||||||
type="email"
|
|
||||||
autoFocus
|
|
||||||
value={formState.email.value}
|
|
||||||
onChange={(e): void => updateForm('email', e.target)}
|
|
||||||
required
|
|
||||||
id="signupEmail"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label htmlFor="signupFirstName">First Name</label>
|
|
||||||
<Input
|
|
||||||
placeholder="Mike"
|
|
||||||
value={formState.firstName.value}
|
|
||||||
onChange={(e): void => updateForm('firstName', e.target)}
|
|
||||||
required
|
|
||||||
id="signupFirstName"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ButtonContainer>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
htmlType="submit"
|
|
||||||
data-attr="signup"
|
|
||||||
loading={loading}
|
|
||||||
disabled={loading || !formState.email.value}
|
|
||||||
>
|
|
||||||
Get Started
|
|
||||||
</Button>
|
|
||||||
</ButtonContainer>
|
|
||||||
</form>
|
|
||||||
</FormWrapper>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
interface DispatchProps {
|
export default SignUp;
|
||||||
loggedIn: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapDispatchToProps = (
|
|
||||||
dispatch: ThunkDispatch<unknown, unknown, AppActions>,
|
|
||||||
): DispatchProps => ({
|
|
||||||
loggedIn: bindActionCreators(UserLoggedIn, dispatch),
|
|
||||||
});
|
|
||||||
|
|
||||||
type SignupProps = DispatchProps;
|
|
||||||
|
|
||||||
export default connect(null, mapDispatchToProps)(Signup);
|
|
||||||
|
@ -1,31 +1,53 @@
|
|||||||
import { Space, Typography } from 'antd';
|
import { Card, Space } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
export const Container = styled(Space)`
|
export const Container = styled.div`
|
||||||
&&& {
|
&&& {
|
||||||
padding-left: 2rem;
|
display: flex;
|
||||||
margin-top: 3rem;
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
|
||||||
|
max-width: 1024px;
|
||||||
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Title = styled(Typography)`
|
export const FormWrapper = styled(Card)`
|
||||||
&&& {
|
|
||||||
font-size: 1rem;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const FormWrapper = styled.div`
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
max-width: 432px;
|
||||||
|
flex: 1;
|
||||||
|
`;
|
||||||
|
|
||||||
margin-top: 2rem;
|
export const Label = styled.label`
|
||||||
|
margin-bottom: 11px;
|
||||||
|
margin-top: 19px;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 24px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const LeftContainer = styled(Space)`
|
||||||
|
flex: 1;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ButtonContainer = styled.div`
|
export const ButtonContainer = styled.div`
|
||||||
margin-top: 0.5rem;
|
margin-top: 1.8125rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const LogoImageContainer = styled.img`
|
interface Props {
|
||||||
width: 320px;
|
marginTop: React.CSSProperties['marginTop'];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MarginTop = styled.div<Props>`
|
||||||
|
margin-top: ${({ marginTop }) => marginTop};
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Logo = styled.img`
|
||||||
|
width: 60px;
|
||||||
`;
|
`;
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
export * from './toggleDarkMode';
|
export * from './toggleDarkMode';
|
||||||
export * from './toggleSettingsTab';
|
export * from './toggleSettingsTab';
|
||||||
export * from './userLoggedIn';
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
import { IS_LOGGED_IN } from 'constants/auth';
|
|
||||||
import { Dispatch } from 'redux';
|
|
||||||
import AppActions from 'types/actions';
|
|
||||||
import setLocalStorageKey from 'api/browser/localstorage/set';
|
|
||||||
|
|
||||||
export const UserLoggedIn = (): ((dispatch: Dispatch<AppActions>) => void) => {
|
|
||||||
return (dispatch: Dispatch<AppActions>): void => {
|
|
||||||
setLocalStorageKey(IS_LOGGED_IN, 'yes');
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: 'LOGGED_IN',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
6
frontend/src/types/api/user/getUserPreference.ts
Normal file
6
frontend/src/types/api/user/getUserPreference.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export interface PayloadProps {
|
||||||
|
hasOptedUpdates: boolean;
|
||||||
|
id: number;
|
||||||
|
isAnonymous: boolean;
|
||||||
|
uuid: string;
|
||||||
|
}
|
3
frontend/src/types/api/user/getVersion.ts
Normal file
3
frontend/src/types/api/user/getVersion.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export interface PayloadProps {
|
||||||
|
version: string;
|
||||||
|
}
|
8
frontend/src/types/api/user/setUserPreference.ts
Normal file
8
frontend/src/types/api/user/setUserPreference.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export interface Props {
|
||||||
|
isAnonymous: boolean;
|
||||||
|
hasOptedUpdates: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PayloadProps {
|
||||||
|
data: string;
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
export interface Props {
|
export interface Props {
|
||||||
email: string;
|
email: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
organizationName: string;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user