Merge branch 'release' of gitlab.com:theappsmith/internal-tools-client into feature/fix-71
This commit is contained in:
commit
c6906e1781
|
|
@ -1,16 +0,0 @@
|
|||
Concepts
|
||||
========
|
||||
Widgets
|
||||
- WidgetProperties
|
||||
- WIDGET_PROPERTY_LABEL (STRING)
|
||||
- WIDGET_PROPERTY_TYPE (STRING)
|
||||
- WIDGET_PROPERTY_DEFAULT (STRING)
|
||||
- WIDGET_PROPERTY_ENABLED (BOOLEAN)
|
||||
- WIDGET_PROPERTY_META
|
||||
- ALLOWED_VALUES (LIST<STRING>)
|
||||
- Components
|
||||
- WidgetCards
|
||||
- WIDGET_TYPE (STRING)
|
||||
- WIDGET_CARD_LABEL (STRING)
|
||||
- WIDGET_CARD_ENABLED (BOOLEAN)
|
||||
- WIDGET_CARD_ICON (UTF-16)
|
||||
|
|
@ -86,7 +86,7 @@
|
|||
"scripts": {
|
||||
"analyze": "source-map-explorer 'build/static/js/*.js'",
|
||||
"start": "REACT_APP_ENVIRONMENT=DEVELOPMENT HOST=dev.appsmith.com craco start",
|
||||
"build": "craco --max-old-space-size=2048 build",
|
||||
"build": "craco --max-old-space-size=2048 build",
|
||||
"test": "CI=true craco test",
|
||||
"eject": "react-scripts eject",
|
||||
"start-prod": "REACT_APP_ENVIRONMENT=PRODUCTION craco start",
|
||||
|
|
|
|||
59
app/client/src/actions/userActions.ts
Normal file
59
app/client/src/actions/userActions.ts
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
import {
|
||||
ReduxActionTypes,
|
||||
ReduxActionErrorTypes,
|
||||
} from "constants/ReduxActionConstants";
|
||||
import { CurrentUserDetailsRequestPayload } from "constants/userConstants";
|
||||
import { VerifyTokenRequest, TokenPasswordUpdateRequest } from "api/UserApi";
|
||||
|
||||
export const logoutUserSuccess = () => ({
|
||||
type: ReduxActionTypes.LOGOUT_USER_SUCCESS,
|
||||
});
|
||||
|
||||
export const logoutUserError = (error: any) => ({
|
||||
type: ReduxActionErrorTypes.LOGOUT_USER_ERROR,
|
||||
payload: {
|
||||
error,
|
||||
},
|
||||
});
|
||||
|
||||
export const fetchCurrentUser = () => ({
|
||||
type: ReduxActionTypes.FETCH_USER_INIT,
|
||||
payload: CurrentUserDetailsRequestPayload,
|
||||
});
|
||||
|
||||
export const setCurrentUserDetails = () => ({
|
||||
type: ReduxActionTypes.SET_CURRENT_USER_INIT,
|
||||
payload: CurrentUserDetailsRequestPayload,
|
||||
});
|
||||
|
||||
export const verifyInviteSuccess = () => ({
|
||||
type: ReduxActionTypes.VERIFY_INVITE_SUCCESS,
|
||||
});
|
||||
|
||||
export const verifyInvite = (payload: VerifyTokenRequest) => ({
|
||||
type: ReduxActionTypes.VERIFY_INVITE_INIT,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const verifyInviteError = (error: any) => ({
|
||||
type: ReduxActionErrorTypes.VERIFY_INVITE_ERROR,
|
||||
payload: { error },
|
||||
});
|
||||
|
||||
export const invitedUserSignup = (
|
||||
payload: TokenPasswordUpdateRequest & { resolve: any; reject: any },
|
||||
) => ({
|
||||
type: ReduxActionTypes.INVITED_USER_SIGNUP,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const invitedUserSignupSuccess = () => ({
|
||||
type: ReduxActionTypes.INVITED_USER_SIGNUP_SUCCESS,
|
||||
});
|
||||
|
||||
export const invitedUserSignupError = (error: any) => ({
|
||||
type: ReduxActionErrorTypes.INVITED_USER_SIGNUP_ERROR,
|
||||
payload: {
|
||||
error,
|
||||
},
|
||||
});
|
||||
|
|
@ -57,6 +57,7 @@ export interface RestAction {
|
|||
pageId?: string;
|
||||
actionConfiguration: Partial<APIConfigRequest>;
|
||||
jsonPathKeys: string[];
|
||||
cacheResponse?: string;
|
||||
}
|
||||
|
||||
export interface ExecuteActionRequest extends APIRequest {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { AxiosPromise } from "axios";
|
||||
import Api from "./Api";
|
||||
import { ApiResponse } from "./ApiResponses";
|
||||
import { getAppsmithConfigs } from "configs";
|
||||
|
||||
export interface LoginUserRequest {
|
||||
email: string;
|
||||
|
|
@ -21,15 +22,13 @@ export interface ForgotPasswordRequest {
|
|||
email: string;
|
||||
}
|
||||
|
||||
export interface ResetPasswordRequest {
|
||||
export interface TokenPasswordUpdateRequest {
|
||||
token: string;
|
||||
user: {
|
||||
password: string;
|
||||
email: string;
|
||||
};
|
||||
password: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
export interface ResetPasswordVerifyTokenRequest {
|
||||
export interface VerifyTokenRequest {
|
||||
email: string;
|
||||
token: string;
|
||||
}
|
||||
|
|
@ -49,45 +48,67 @@ export interface InviteUserRequest {
|
|||
}
|
||||
|
||||
class UserApi extends Api {
|
||||
//TODO(abhinav): make a baseURL, to which the other paths are added.
|
||||
static createURL = "v1/users";
|
||||
static forgotPasswordURL = "v1/users/forgotPassword";
|
||||
static verifyResetPasswordTokenURL = "v1/users/verifyPasswordResetToken";
|
||||
static resetPasswordURL = "v1/users/resetPassword";
|
||||
static fetchUserURL = "v1/users";
|
||||
static usersURL = "v1/users";
|
||||
static forgotPasswordURL = `${UserApi.usersURL}/forgotPassword`;
|
||||
static verifyResetPasswordTokenURL = `${UserApi.usersURL}/verifyPasswordResetToken`;
|
||||
static resetPasswordURL = `${UserApi.usersURL}/resetPassword`;
|
||||
static inviteUserURL = "v1/users/invite";
|
||||
static verifyInviteTokenURL = `${UserApi.inviteUserURL}/verify`;
|
||||
static confirmUserInviteURL = `${UserApi.inviteUserURL}/confirm`;
|
||||
static logoutURL = "/logout";
|
||||
|
||||
static createUser(
|
||||
request: CreateUserRequest,
|
||||
): AxiosPromise<CreateUserResponse> {
|
||||
return Api.post(UserApi.createURL, request);
|
||||
return Api.post(UserApi.usersURL, request);
|
||||
}
|
||||
|
||||
static fetchUser(request: FetchUserRequest): AxiosPromise<FetchUserResponse> {
|
||||
return Api.get(UserApi.usersURL + "/" + request.id);
|
||||
}
|
||||
|
||||
static forgotPassword(
|
||||
request: ForgotPasswordRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.get(UserApi.forgotPasswordURL, request);
|
||||
}
|
||||
|
||||
static resetPassword(
|
||||
request: ResetPasswordRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.put(UserApi.resetPasswordURL, request);
|
||||
return Api.post(UserApi.forgotPasswordURL, request);
|
||||
}
|
||||
|
||||
static verifyResetPasswordToken(
|
||||
request: ResetPasswordVerifyTokenRequest,
|
||||
request: VerifyTokenRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.get(UserApi.verifyResetPasswordTokenURL, request);
|
||||
}
|
||||
|
||||
static fetchUser(request: FetchUserRequest): AxiosPromise<FetchUserResponse> {
|
||||
return Api.get(UserApi.fetchUserURL + "/" + request.id);
|
||||
static resetPassword(
|
||||
request: TokenPasswordUpdateRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.put(UserApi.resetPasswordURL, request);
|
||||
}
|
||||
|
||||
static inviteUser(request: InviteUserRequest): AxiosPromise<ApiResponse> {
|
||||
request.status = "INVITED";
|
||||
return Api.post(UserApi.inviteUserURL, request);
|
||||
}
|
||||
|
||||
static verifyUserInvite(
|
||||
request: VerifyTokenRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.get(UserApi.verifyInviteTokenURL, request);
|
||||
}
|
||||
|
||||
static confirmInvitedUserSignup(
|
||||
request: TokenPasswordUpdateRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.put(UserApi.confirmUserInviteURL, request);
|
||||
}
|
||||
|
||||
static logoutUser(): AxiosPromise<ApiResponse> {
|
||||
const { baseUrl } = getAppsmithConfigs();
|
||||
return Api.post(UserApi.logoutURL, undefined, undefined, {
|
||||
baseURL: baseUrl,
|
||||
withCredentials: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default UserApi;
|
||||
|
|
|
|||
|
|
@ -14,9 +14,14 @@ type DropdownProps = {
|
|||
meta: WrappedFieldMetaProps;
|
||||
onCreateOption: (inputValue: string) => void;
|
||||
formatCreateLabel?: (value: string) => React.ReactNode;
|
||||
noOptionsMessage?: (obj: { inputValue: string }) => string;
|
||||
};
|
||||
|
||||
const selectStyles = {
|
||||
placeholder: (provided: any) => ({
|
||||
...provided,
|
||||
color: "#a3b3bf",
|
||||
}),
|
||||
singleValue: (provided: any) => ({
|
||||
...provided,
|
||||
backgroundColor: "rgba(104,113,239,0.1)",
|
||||
|
|
@ -67,9 +72,11 @@ class CreatableDropdown extends React.Component<DropdownProps> {
|
|||
onCreateOption,
|
||||
input,
|
||||
formatCreateLabel,
|
||||
noOptionsMessage,
|
||||
} = this.props;
|
||||
const optionalProps: Partial<DropdownProps> = {};
|
||||
if (formatCreateLabel) optionalProps.formatCreateLabel = formatCreateLabel;
|
||||
if (noOptionsMessage) optionalProps.noOptionsMessage = noOptionsMessage;
|
||||
return (
|
||||
<Creatable
|
||||
placeholder={placeholder}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ type DropdownProps = {
|
|||
};
|
||||
|
||||
const selectStyles = {
|
||||
placeholder: (provided: any) => ({
|
||||
...provided,
|
||||
color: "#a3b3bf",
|
||||
}),
|
||||
control: (styles: any, state: any) => ({
|
||||
...styles,
|
||||
width: 100,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import React from "react";
|
||||
import { AnchorButton, IButtonProps, MaybeElement } from "@blueprintjs/core";
|
||||
import styled, { css } from "styled-components";
|
||||
import { TextComponentProps } from "./TextComponent";
|
||||
import { ButtonStyle } from "widgets/ButtonWidget";
|
||||
import { Theme } from "constants/DefaultTheme";
|
||||
import _ from "lodash";
|
||||
import { ComponentProps } from "components/designSystems/appsmith/BaseComponent";
|
||||
|
||||
const getButtonColorStyles = (props: { theme: Theme } & ButtonStyleProps) => {
|
||||
if (props.filled) return props.theme.colors.textOnDarkBG;
|
||||
|
|
@ -98,7 +98,8 @@ BaseButton.defaultProps = {
|
|||
minimal: true,
|
||||
};
|
||||
|
||||
interface ButtonContainerProps extends TextComponentProps {
|
||||
interface ButtonContainerProps extends ComponentProps {
|
||||
text?: string;
|
||||
icon?: MaybeElement;
|
||||
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
|
||||
disabled?: boolean;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ export interface TextComponentProps extends ComponentProps {
|
|||
ellipsize?: boolean;
|
||||
textStyle?: TextStyle;
|
||||
isLoading: boolean;
|
||||
allowHtml: boolean;
|
||||
}
|
||||
|
||||
class TextComponent extends React.Component<TextComponentProps> {
|
||||
|
|
@ -37,14 +38,22 @@ class TextComponent extends React.Component<TextComponentProps> {
|
|||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Text
|
||||
className={this.getTextClass(this.props.textStyle)}
|
||||
ellipsize={this.props.ellipsize}
|
||||
>
|
||||
{this.props.text}
|
||||
</Text>
|
||||
);
|
||||
const { allowHtml, textStyle, text, ellipsize } = this.props;
|
||||
if (allowHtml && text) {
|
||||
const markup = { __html: text };
|
||||
return (
|
||||
<div
|
||||
dangerouslySetInnerHTML={markup}
|
||||
className={this.getTextClass(textStyle)}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Text className={this.getTextClass(textStyle)} ellipsize={ellipsize}>
|
||||
{text}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import {
|
|||
Grid,
|
||||
Inject,
|
||||
Resize,
|
||||
Page,
|
||||
SelectionSettingsModel,
|
||||
} from "@syncfusion/ej2-react-grids";
|
||||
import * as React from "react";
|
||||
import styled from "constants/DefaultTheme";
|
||||
|
|
@ -25,38 +27,72 @@ const StyledGridComponent = styled(GridComponent)`
|
|||
background-color: #fafafa;
|
||||
}
|
||||
`;
|
||||
const settings: SelectionSettingsModel = {
|
||||
type: "Multiple",
|
||||
};
|
||||
|
||||
export default class TableComponent extends React.Component<
|
||||
TableComponentProps,
|
||||
{}
|
||||
> {
|
||||
private grid: Grid | null | undefined;
|
||||
public rowSelected = () => {
|
||||
rowSelected = () => {
|
||||
if (this.grid) {
|
||||
/** Get the selected row indexes */
|
||||
const selectedrowindex: number[] = this.grid.getSelectedRowIndexes();
|
||||
/** Get the selected records. */
|
||||
const selectedrecords: object[] = this.grid.getSelectedRecords();
|
||||
this.props.onRowClick(selectedrecords[0], selectedrowindex[0]);
|
||||
if (selectedrecords.length !== 0) {
|
||||
this.props.onRowClick(selectedrecords[0], selectedrowindex[0]);
|
||||
}
|
||||
}
|
||||
};
|
||||
public dataBound = () => {
|
||||
|
||||
reCalculatePageSize = () => {
|
||||
if (this.grid) {
|
||||
/** height of the each row */
|
||||
const rowHeight: number = this.grid.getRowHeight();
|
||||
/** Grid height */
|
||||
const gridHeight: number = this.grid.height as number;
|
||||
/** initial page size */
|
||||
const pageSize: number = this.grid.pageSettings.pageSize as number;
|
||||
/** new page size is obtained here */
|
||||
const pageResize: any = (gridHeight - pageSize * rowHeight) / rowHeight;
|
||||
this.grid.pageSettings.pageSize = pageSize + Math.round(pageResize);
|
||||
}
|
||||
};
|
||||
dataBound = () => {
|
||||
if (this.grid) {
|
||||
this.grid.autoFitColumns();
|
||||
}
|
||||
};
|
||||
public render() {
|
||||
|
||||
shouldComponentUpdate(nextProps: TableComponentProps) {
|
||||
const propsNotEqual =
|
||||
JSON.stringify(nextProps.data) !== JSON.stringify(this.props.data) ||
|
||||
nextProps.height !== this.props.height ||
|
||||
nextProps.width !== this.props.width;
|
||||
|
||||
return propsNotEqual;
|
||||
}
|
||||
componentDidUpdate(prevProps: TableComponentProps) {
|
||||
if (prevProps.height !== this.props.height) {
|
||||
this.reCalculatePageSize();
|
||||
}
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<StyledGridComponent
|
||||
selectionSettings={settings}
|
||||
dataSource={this.props.data}
|
||||
selectedRowIndex={this.props.selectedRowIndex}
|
||||
rowSelected={this.rowSelected}
|
||||
ref={(g: GridComponent) => (this.grid = g)}
|
||||
width={this.props.width - 16}
|
||||
height={this.props.height - 62}
|
||||
height={this.props.height - 107}
|
||||
dataBound={this.dataBound}
|
||||
allowPaging={true}
|
||||
>
|
||||
<Inject services={[Resize]} />
|
||||
<Inject services={[Resize, Page]} />
|
||||
<ColumnsDirective>
|
||||
{this.props.columns.map(col => {
|
||||
return <ColumnDirective key={col.field} field={col.field} />;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { formatBytes } from "utils/helpers";
|
|||
import { APIEditorRouteParams } from "constants/routes";
|
||||
import { ApiPaneReduxState } from "reducers/uiReducers/apiPaneReducer";
|
||||
import LoadingOverlayScreen from "components/editorComponents/LoadingOverlayScreen";
|
||||
import DynamicAutocompleteInput from "components/editorComponents/DynamicAutocompleteInput";
|
||||
import CodeEditor from "components/editorComponents/CodeEditor";
|
||||
|
||||
const ResponseWrapper = styled.div`
|
||||
position: relative;
|
||||
|
|
@ -138,12 +138,13 @@ const ApiResponseView = (props: Props) => {
|
|||
key: "body",
|
||||
title: "Response Body",
|
||||
panelComponent: (
|
||||
<DynamicAutocompleteInput
|
||||
<CodeEditor
|
||||
input={{
|
||||
value: response.body
|
||||
? JSON.stringify(response.body, null, 2)
|
||||
: "",
|
||||
}}
|
||||
height={700}
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -21,19 +21,19 @@ interface Props {
|
|||
class CodeEditor extends React.Component<Props> {
|
||||
textArea = React.createRef<HTMLTextAreaElement>();
|
||||
editor: any;
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
}
|
||||
componentDidMount(): void {
|
||||
if (this.textArea.current) {
|
||||
const readOnly = !this.props.input.onChange;
|
||||
this.editor = cm.fromTextArea(this.textArea.current, {
|
||||
mode: { name: "javascript", json: true },
|
||||
value: this.props.input.value,
|
||||
readOnly,
|
||||
lineNumbers: true,
|
||||
tabSize: 2,
|
||||
indentWithTabs: true,
|
||||
lineWrapping: true,
|
||||
});
|
||||
this.editor.setSize(null, this.props.height);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,43 +1,146 @@
|
|||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { AppState } from "reducers";
|
||||
import styled from "styled-components";
|
||||
import CodeMirror, { EditorConfiguration } from "codemirror";
|
||||
import styled, { createGlobalStyle } from "styled-components";
|
||||
import CodeMirror, { EditorConfiguration, LineHandle } from "codemirror";
|
||||
import "codemirror/lib/codemirror.css";
|
||||
import "codemirror/theme/monokai.css";
|
||||
import "codemirror/addon/hint/show-hint";
|
||||
import "codemirror/addon/hint/show-hint.css";
|
||||
import "codemirror/addon/hint/javascript-hint";
|
||||
import "codemirror/addon/display/placeholder";
|
||||
import {
|
||||
getNameBindingsWithData,
|
||||
getNameBindingsForAutocomplete,
|
||||
NameBindingsWithData,
|
||||
} from "selectors/nameBindingsWithDataSelector";
|
||||
import { AUTOCOMPLETE_MATCH_REGEX } from "constants/BindingsConstants";
|
||||
import ErrorTooltip from "components/editorComponents/ErrorTooltip";
|
||||
import { WrappedFieldInputProps, WrappedFieldMetaProps } from "redux-form";
|
||||
import _ from "lodash";
|
||||
import { parseDynamicString } from "utils/DynamicBindingUtils";
|
||||
require("codemirror/mode/javascript/javascript");
|
||||
|
||||
const Wrapper = styled.div<{ height?: number; theme?: "LIGHT" | "DARK" }>`
|
||||
border: ${props => props.theme !== "DARK" && "1px solid #d0d7dd"};
|
||||
const HintStyles = createGlobalStyle`
|
||||
.CodeMirror-hints {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
overflow: hidden;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 5px;
|
||||
font-size: 90%;
|
||||
font-family: monospace;
|
||||
max-height: 20em;
|
||||
width: 200px;
|
||||
overflow-y: auto;
|
||||
background: #FFFFFF;
|
||||
border: 1px solid #EBEFF2;
|
||||
box-shadow: 0px 2px 4px rgba(67, 70, 74, 0.14);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.CodeMirror-hint {
|
||||
height: 32px;
|
||||
padding: 3px;
|
||||
margin: 0;
|
||||
white-space: pre;
|
||||
color: #2E3D49;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
li.CodeMirror-hint-active {
|
||||
background: #E9FAF3;
|
||||
border-radius: 4px;
|
||||
}
|
||||
`;
|
||||
|
||||
const Wrapper = styled.div<{
|
||||
borderStyle?: THEME;
|
||||
hasError: boolean;
|
||||
}>`
|
||||
border: 1px solid;
|
||||
border-color: ${props =>
|
||||
props.hasError
|
||||
? props.theme.colors.error
|
||||
: props.borderStyle !== THEMES.DARK
|
||||
? "#d0d7dd"
|
||||
: "transparent"};
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
flex-direction: row;
|
||||
position: relative;
|
||||
text-transform: none;
|
||||
min-height: 32px;
|
||||
height: ${props => (props.height ? `${props.height}px` : "32px")};
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
&& {
|
||||
.binding-highlight {
|
||||
color: ${props =>
|
||||
props.borderStyle === THEMES.DARK ? "#f7c75b" : "#ffb100"};
|
||||
font-weight: 700;
|
||||
}
|
||||
.CodeMirror {
|
||||
flex: 1;
|
||||
line-height: 21px;
|
||||
z-index: 0;
|
||||
border-radius: 4px;
|
||||
height: auto;
|
||||
}
|
||||
.CodeMirror pre.CodeMirror-placeholder {
|
||||
color: #a3b3bf;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const IconContainer = styled.div`
|
||||
.bp3-icon {
|
||||
border-radius: 4px 0 0 4px;
|
||||
margin: 0;
|
||||
height: 32px;
|
||||
width: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #eef2f5;
|
||||
svg {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
path {
|
||||
fill: #979797;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const THEMES = {
|
||||
LIGHT: "LIGHT",
|
||||
DARK: "DARK",
|
||||
};
|
||||
|
||||
type THEME = "LIGHT" | "DARK";
|
||||
|
||||
interface ReduxStateProps {
|
||||
dynamicData: NameBindingsWithData;
|
||||
}
|
||||
|
||||
type Props = ReduxStateProps & {
|
||||
input: {
|
||||
value: string;
|
||||
onChange?: (value: string) => void;
|
||||
};
|
||||
theme?: "LIGHT" | "DARK";
|
||||
export type DynamicAutocompleteInputProps = {
|
||||
placeholder?: string;
|
||||
leftIcon?: Function;
|
||||
height?: number;
|
||||
theme?: THEME;
|
||||
meta?: Partial<WrappedFieldMetaProps>;
|
||||
showLineNumbers?: boolean;
|
||||
allowTabIndent?: boolean;
|
||||
};
|
||||
|
||||
type Props = ReduxStateProps &
|
||||
DynamicAutocompleteInputProps & {
|
||||
input: Partial<WrappedFieldInputProps>;
|
||||
};
|
||||
|
||||
class DynamicAutocompleteInput extends Component<Props> {
|
||||
textArea = React.createRef<HTMLTextAreaElement>();
|
||||
editor: any;
|
||||
|
|
@ -47,31 +150,45 @@ class DynamicAutocompleteInput extends Component<Props> {
|
|||
const options: EditorConfiguration = {};
|
||||
if (this.props.theme === "DARK") options.theme = "monokai";
|
||||
if (!this.props.input.onChange) options.readOnly = true;
|
||||
if (this.props.showLineNumbers) options.lineNumbers = true;
|
||||
const extraKeys: Record<string, any> = {
|
||||
"Ctrl-Space": "autocomplete",
|
||||
};
|
||||
if (!this.props.allowTabIndent) extraKeys["Tab"] = false;
|
||||
this.editor = CodeMirror.fromTextArea(this.textArea.current, {
|
||||
mode: { name: "javascript", globalVars: true },
|
||||
viewportMargin: 10,
|
||||
value: this.props.input.value,
|
||||
tabSize: 2,
|
||||
indentWithTabs: true,
|
||||
lineWrapping: true,
|
||||
extraKeys: { "Ctrl-Space": "autocomplete" },
|
||||
showHint: true,
|
||||
extraKeys,
|
||||
...options,
|
||||
});
|
||||
this.editor.on("change", this.handleChange);
|
||||
this.editor.on("keyup", this.handleAutocompleteVisibility);
|
||||
this.editor.on("change", _.debounce(this.handleChange, 200));
|
||||
this.editor.on("cursorActivity", this.handleAutocompleteVisibility);
|
||||
this.editor.setOption("hintOptions", {
|
||||
completeSingle: false,
|
||||
globalScope: this.props.dynamicData,
|
||||
});
|
||||
if (this.props.height) {
|
||||
this.editor.setSize(0, this.props.height);
|
||||
}
|
||||
this.editor.eachLine(this.highlightBindings);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(): void {
|
||||
if (this.editor) {
|
||||
const editorValue = this.editor.getValue();
|
||||
const inputValue = this.props.input.value;
|
||||
if (inputValue && inputValue !== editorValue) {
|
||||
let inputValue = this.props.input.value;
|
||||
if (typeof inputValue === "object") {
|
||||
inputValue = JSON.stringify(inputValue, null, 2);
|
||||
}
|
||||
if ((!!inputValue || inputValue === "") && inputValue !== editorValue) {
|
||||
this.editor.setValue(inputValue);
|
||||
this.editor.setCursor(this.editor.lineCount(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -81,27 +198,82 @@ class DynamicAutocompleteInput extends Component<Props> {
|
|||
if (this.props.input.onChange) {
|
||||
this.props.input.onChange(value);
|
||||
}
|
||||
this.editor.eachLine(this.highlightBindings);
|
||||
};
|
||||
|
||||
handleAutocompleteVisibility = (cm: any, event: any) => {
|
||||
if (!cm.state.completionActive && event.keyCode !== 13) {
|
||||
handleAutocompleteVisibility = (cm: any) => {
|
||||
let cursorBetweenBinding = false;
|
||||
const cursor = this.editor.getCursor();
|
||||
const value = this.editor.getValue();
|
||||
let cumulativeCharCount = 0;
|
||||
parseDynamicString(value).forEach(segment => {
|
||||
const start = cumulativeCharCount;
|
||||
const dynamicStart = segment.indexOf("{{");
|
||||
const dynamicDoesStart = dynamicStart > -1;
|
||||
const dynamicEnd = segment.indexOf("}}");
|
||||
const dynamicDoesEnd = dynamicEnd > -1;
|
||||
const dynamicStartIndex = dynamicStart + start + 1;
|
||||
const dynamicEndIndex = dynamicEnd + start + 1;
|
||||
if (
|
||||
dynamicDoesStart &&
|
||||
cursor.ch > dynamicStartIndex &&
|
||||
((dynamicDoesEnd && cursor.ch < dynamicEndIndex) ||
|
||||
(!dynamicDoesEnd && cursor.ch > dynamicStartIndex))
|
||||
) {
|
||||
cursorBetweenBinding = true;
|
||||
}
|
||||
cumulativeCharCount = start + segment.length;
|
||||
});
|
||||
const shouldShow = cursorBetweenBinding && !cm.state.completionActive;
|
||||
if (shouldShow) {
|
||||
cm.showHint(cm);
|
||||
}
|
||||
};
|
||||
|
||||
highlightBindings = (line: LineHandle) => {
|
||||
const lineNo = this.editor.getLineNumber(line);
|
||||
let match;
|
||||
while ((match = AUTOCOMPLETE_MATCH_REGEX.exec(line.text)) != null) {
|
||||
const start = match.index;
|
||||
const end = AUTOCOMPLETE_MATCH_REGEX.lastIndex;
|
||||
this.editor.markText(
|
||||
{ ch: start, line: lineNo },
|
||||
{ ch: end, line: lineNo },
|
||||
{
|
||||
className: "binding-highlight",
|
||||
},
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { input, theme } = this.props;
|
||||
const height = this.editor ? this.editor.doc.height + 20 : null;
|
||||
const { input, meta, theme } = this.props;
|
||||
const hasError = !!(meta && meta.error);
|
||||
let showError = false;
|
||||
if (this.editor) {
|
||||
showError = hasError && this.editor.hasFocus();
|
||||
}
|
||||
return (
|
||||
<Wrapper height={height} theme={theme}>
|
||||
<textarea ref={this.textArea} defaultValue={input.value} />
|
||||
</Wrapper>
|
||||
<ErrorTooltip message={meta ? meta.error : ""} isOpen={showError}>
|
||||
<Wrapper borderStyle={theme} hasError={hasError}>
|
||||
<HintStyles />
|
||||
<IconContainer>
|
||||
{this.props.leftIcon && <this.props.leftIcon />}
|
||||
</IconContainer>
|
||||
<textarea
|
||||
ref={this.textArea}
|
||||
{..._.omit(this.props.input, ["onChange", "value"])}
|
||||
defaultValue={input.value}
|
||||
placeholder={this.props.placeholder}
|
||||
/>
|
||||
</Wrapper>
|
||||
</ErrorTooltip>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: AppState): ReduxStateProps => ({
|
||||
dynamicData: getNameBindingsWithData(state),
|
||||
dynamicData: getNameBindingsForAutocomplete(state),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(DynamicAutocompleteInput);
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ import { Popover } from "@blueprintjs/core";
|
|||
import styled from "styled-components";
|
||||
|
||||
const Wrapper = styled.div`
|
||||
flex: 1;
|
||||
.bp3-popover-target {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.bp3-popover {
|
||||
.bp3-popover-arrow {
|
||||
|
|
|
|||
|
|
@ -58,16 +58,24 @@ const TagInputComponent = (props: TagInputProps) => {
|
|||
props.input.onChange &&
|
||||
props.input.onChange(newValues.filter(Boolean).join(","));
|
||||
};
|
||||
|
||||
const onTagsChange = (values: React.ReactNode[]) => {
|
||||
const _values = values as string[];
|
||||
commitValues(_values);
|
||||
};
|
||||
|
||||
const onKeyDown = (e: any) => {
|
||||
if (e.key === "," || e.key === "Enter" || e.key === " ") {
|
||||
// Add new values to the tags on comma, return key, space and Tab press.
|
||||
if (
|
||||
e.key === "," ||
|
||||
e.key === "Enter" ||
|
||||
e.key === " " ||
|
||||
e.key === "Tab"
|
||||
) {
|
||||
const newValues = [...values, e.target.value];
|
||||
commitValues(newValues);
|
||||
setCurrentValue("");
|
||||
e.preventDefault();
|
||||
} else if (e.key === "Backspace") {
|
||||
if (e.target.value.length === 0) {
|
||||
const newValues = values.slice(0, -1);
|
||||
|
|
@ -76,9 +84,13 @@ const TagInputComponent = (props: TagInputProps) => {
|
|||
}
|
||||
};
|
||||
|
||||
// The input text field where the user can type in needs to handle the scenario where
|
||||
// The input field is reset on adding tag.
|
||||
const handleInputChange = (e: any) => {
|
||||
if ([",", " ", "Enter"].indexOf(e.target.value) === -1) {
|
||||
setCurrentValue(e.target.value);
|
||||
} else {
|
||||
setCurrentValue("");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -90,7 +102,6 @@ const TagInputComponent = (props: TagInputProps) => {
|
|||
placeholder={props.placeholder}
|
||||
values={_values || [""]}
|
||||
separator={props.separator || ","}
|
||||
addOnBlur
|
||||
addOnPaste
|
||||
onChange={onTagsChange}
|
||||
onKeyDown={onKeyDown}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ type FormFooterProps = {
|
|||
submitText?: string;
|
||||
cancelText?: string;
|
||||
submitOnEnter?: boolean;
|
||||
canSubmit: boolean;
|
||||
};
|
||||
|
||||
const FooterActions = styled.div`
|
||||
|
|
@ -46,6 +47,7 @@ export const FormFooter = (props: FormFooterProps) => {
|
|||
type={props.submitOnEnter ? "submit" : "button"}
|
||||
intent="primary"
|
||||
onClick={props.onSubmit}
|
||||
disabled={!props.canSubmit}
|
||||
loading={props.submitting}
|
||||
large
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -37,11 +37,12 @@ const DatasourcesField = (
|
|||
component={CreatableDropdown}
|
||||
isLoading={props.datasources.loading}
|
||||
options={options}
|
||||
placeholder="Data Source"
|
||||
placeholder="https://<base-url>.com"
|
||||
onCreateOption={props.createDatasource}
|
||||
format={(value: string) => _.find(options, { value })}
|
||||
parse={(option: { value: string }) => (option ? option.value : null)}
|
||||
formatCreateLabel={(value: string) => `Create data source "${value}"`}
|
||||
noOptionsMessage={() => "No data sources created"}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import React from "react";
|
||||
import { Field, BaseFieldProps } from "redux-form";
|
||||
import { TextInputProps } from "components/designSystems/appsmith/TextInputComponent";
|
||||
import DynamicAutocompleteInput from "components/editorComponents/DynamicAutocompleteInput";
|
||||
import DynamicAutocompleteInput, {
|
||||
DynamicAutocompleteInputProps,
|
||||
} from "components/editorComponents/DynamicAutocompleteInput";
|
||||
|
||||
class DynamicTextField extends React.Component<
|
||||
BaseFieldProps & TextInputProps
|
||||
BaseFieldProps & DynamicAutocompleteInputProps
|
||||
> {
|
||||
render() {
|
||||
return <Field component={DynamicAutocompleteInput} {...this.props} />;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
import React from "react";
|
||||
import { Field } from "redux-form";
|
||||
import DynamicAutocompleteInput from "components/editorComponents/DynamicAutocompleteInput";
|
||||
import DynamicAutocompleteInput, {
|
||||
DynamicAutocompleteInputProps,
|
||||
} from "components/editorComponents/DynamicAutocompleteInput";
|
||||
|
||||
const JSONEditorField = (props: { name: string }) => {
|
||||
type Props = { name: string } & DynamicAutocompleteInputProps;
|
||||
|
||||
const JSONEditorField = (props: Props) => {
|
||||
return <Field name={props.name} component={DynamicAutocompleteInput} />;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,11 @@ const renderComponent = (
|
|||
<TagInputComponent {...componentProps} />
|
||||
|
||||
<FormFieldError
|
||||
error={componentProps.meta.touched && componentProps.meta.error}
|
||||
error={
|
||||
componentProps.meta.touched &&
|
||||
!componentProps.meta.pristine &&
|
||||
componentProps.meta.error
|
||||
}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import React from "react";
|
||||
import React, { ChangeEvent } from "react";
|
||||
import BaseControl, { ControlProps } from "./BaseControl";
|
||||
import { ControlType } from "constants/PropertyControlConstants";
|
||||
import { ControlWrapper } from "./StyledControls";
|
||||
import DynamicAutocompleteInput from "components/editorComponents/DynamicAutocompleteInput";
|
||||
import { EventOrValueHandler } from "redux-form";
|
||||
class CodeEditorControl extends BaseControl<ControlProps> {
|
||||
render() {
|
||||
return (
|
||||
|
|
@ -16,7 +17,9 @@ class CodeEditorControl extends BaseControl<ControlProps> {
|
|||
);
|
||||
}
|
||||
|
||||
onChange = (value: string) => {
|
||||
onChange: EventOrValueHandler<ChangeEvent<any>> = (
|
||||
value: string | ChangeEvent,
|
||||
) => {
|
||||
this.updateProperty(this.props.propertyName, value);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -8,12 +8,7 @@ import DynamicAutocompleteInput from "components/editorComponents/DynamicAutocom
|
|||
|
||||
class InputTextControl extends BaseControl<InputControlProps> {
|
||||
render() {
|
||||
const {
|
||||
// validationMessage,
|
||||
propertyValue,
|
||||
// isValid,
|
||||
label,
|
||||
} = this.props;
|
||||
const { validationMessage, propertyValue, isValid, label } = this.props;
|
||||
return (
|
||||
<ControlWrapper>
|
||||
<label>{label}</label>
|
||||
|
|
@ -23,6 +18,10 @@ class InputTextControl extends BaseControl<InputControlProps> {
|
|||
value: propertyValue,
|
||||
onChange: this.onTextChange,
|
||||
}}
|
||||
meta={{
|
||||
error: isValid ? "" : validationMessage,
|
||||
touched: true,
|
||||
}}
|
||||
theme={"DARK"}
|
||||
/>
|
||||
</StyledDynamicInput>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,5 @@
|
|||
// TODO (hetu): Remove useless escapes and re-enable the above lint rule
|
||||
export type NamePathBindingMap = Record<string, string>;
|
||||
export const DATA_BIND_REGEX = /(.*?){{(\s*(.*?)\s*)}}(.*?)/g;
|
||||
export const DATA_PATH_REGEX = /[\w\.\[\]\d]+/;
|
||||
export const DATA_BIND_AUTOCOMPLETE = /({{)(.*)(}{0,2}?)/;
|
||||
export const AUTOCOMPLETE_MATCH_REGEX = /{{\s*.*?\s*}}/g;
|
||||
/* eslint-enable no-useless-escape */
|
||||
|
|
|
|||
|
|
@ -106,8 +106,6 @@ export const ReduxActionTypes: { [key: string]: string } = {
|
|||
EXECUTE_PAGE_LOAD_ACTIONS: "EXECUTE_PAGE_LOAD_ACTIONS",
|
||||
SWITCH_ORGANIZATION_INIT: "SWITCH_ORGANIZATION_INIT",
|
||||
SWITCH_ORGANIZATION_SUCCESS: "SWITCH_ORGANIZATION_SUCCESS",
|
||||
LOGOUT_USER_INIT: "LOGOUT_USER_INIT",
|
||||
LOGOUT_USER_SUCCESS: "LOGOUT_USER_SUCCESS",
|
||||
FETCH_ORG_ROLES_INIT: "FETCH_ORG_ROLES_INIT",
|
||||
FETCH_ORG_ROLES_SUCCESS: "FETCH_ORG_ROLES_SUCCESS",
|
||||
FETCH_ORG_INIT: "FETCH_ORG_INIT",
|
||||
|
|
@ -119,6 +117,12 @@ export const ReduxActionTypes: { [key: string]: string } = {
|
|||
FETCH_USER_SUCCESS: "FETCH_USER_SUCCESS",
|
||||
SET_CURRENT_USER_INIT: "SET_CURRENT_USER_INIT",
|
||||
SET_CURRENT_USER_SUCCESS: "SET_CURRENT_USER_SUCCESS",
|
||||
LOGOUT_USER_INIT: "LOGOUT_USER_INIT",
|
||||
LOGOUT_USER_SUCCESS: "LOGOUT_USER_SUCCESS",
|
||||
VERIFY_INVITE_INIT: "VERIFY_INVITE_INIT",
|
||||
VERIFY_INVITE_SUCCESS: "VERIFY_INVITE_SUCCESS",
|
||||
INVITED_USER_SIGNUP_SUCCESS: "INVITED_USER_SIGNUP_SUCCESS",
|
||||
INVITED_USER_SIGNUP_INIT: "INVITED_USER_SIGNUP_INIT",
|
||||
};
|
||||
|
||||
export type ReduxActionType = typeof ReduxActionTypes[keyof typeof ReduxActionTypes];
|
||||
|
|
@ -162,7 +166,6 @@ export const ReduxActionErrorTypes: { [key: string]: string } = {
|
|||
SWITCH_ORGANIZATION_ERROR: "SWITCH_ORGANIZATION_ERROR",
|
||||
FORGOT_PASSWORD_ERROR: "FORGOT_PASSWORD_ERROR",
|
||||
RESET_PASSWORD_VERIFY_TOKEN_ERROR: "RESET_PASSWORD_VERIFY_TOKEN_ERROR",
|
||||
LOGOUT_USER_ERROR: "LOGOUT_USER_ERROR",
|
||||
FETCH_ORG_ROLES_ERROR: "FETCH_ORG_ROLES_ERROR",
|
||||
INVITE_USERS_TO_ORG_ERROR: "INVITE_USERS_TO_ORG_ERROR",
|
||||
SAVE_ORG_ERROR: "SAVE_ORG_ERROR",
|
||||
|
|
@ -170,6 +173,8 @@ export const ReduxActionErrorTypes: { [key: string]: string } = {
|
|||
FETCH_ORGS_ERROR: "FETCH_ORGS_ERROR",
|
||||
FETCH_USER_ERROR: "FETCH_USER_ERROR",
|
||||
SET_CURRENT_USER_ERROR: "SET_CURRENT_USER_ERROR",
|
||||
LOGOUT_USER_ERROR: "LOGOUT_USER_ERROR",
|
||||
VERIFY_INVITE_ERROR: "VERIFY_INVITE_ERROR",
|
||||
};
|
||||
|
||||
export const ReduxFormActionTypes: { [key: string]: string } = {
|
||||
|
|
@ -190,6 +195,13 @@ export type ReduxActionWithoutPayload = Pick<ReduxAction<undefined>, "type">;
|
|||
export interface ReduxActionWithMeta<T, M> extends ReduxAction<T> {
|
||||
meta: M;
|
||||
}
|
||||
export interface PromisePayload {
|
||||
reject: any;
|
||||
resolve: any;
|
||||
}
|
||||
export interface ReduxActionWithPromise<T> extends ReduxAction<T> {
|
||||
payload: T & PromisePayload;
|
||||
}
|
||||
|
||||
export interface ReduxActionErrorPayload {
|
||||
message: string;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@ export const API_EDITOR_FORM_NAME = "ApiEditorForm";
|
|||
export const CREATE_APPLICATION_FORM_NAME = "CreateApplicationForm";
|
||||
export const INVITE_USERS_TO_ORG_FORM = "InviteUsersToOrgForm";
|
||||
export const LOGIN_FORM_NAME = "LoginForm";
|
||||
|
||||
export const LOGIN_FORM_EMAIL_FIELD_NAME = "username";
|
||||
export const LOGIN_FORM_PASSWORD_FIELD_NAME = "password";
|
||||
|
||||
export const SIGNUP_FORM_NAME = "SignupForm";
|
||||
export const FORGOT_PASSWORD_FORM_NAME = "ForgotPasswordForm";
|
||||
export const RESET_PASSWORD_FORM_NAME = "ResetPasswordForm";
|
||||
export const CREATE_PASSWORD_FORM_NAME = "CreatePasswordForm";
|
||||
|
|
|
|||
|
|
@ -99,3 +99,21 @@ export const INVITE_USERS_SUBMIT_SUCCESS =
|
|||
"The users have been invited successfully";
|
||||
export const INVITE_USERS_VALIDATION_EMAILS_EMPTY =
|
||||
"Please enter the user emails";
|
||||
|
||||
export const CREATE_PASSWORD_PAGE_PASSWORD_INPUT_LABEL = "New Password";
|
||||
export const CREATE_PASSWORD_PAGE_PASSWORD_INPUT_PLACEHOLDER = "New Password";
|
||||
export const CREATE_PASSWORD_LOGIN_LINK_TEXT =
|
||||
"Already know the password? Login";
|
||||
export const CREATE_PASSWORD_PAGE_TITLE = "Set Password";
|
||||
export const CREATE_PASSWORD_SUBMIT_BUTTON_TEXT = "Create";
|
||||
export const CREATE_PASSWORD_PAGE_SUBTITLE =
|
||||
"Set a new password for your account ";
|
||||
|
||||
export const CREATE_PASSWORD_RESET_SUCCESS =
|
||||
"Your password has been set. Please";
|
||||
export const CREATE_PASSWORD_RESET_SUCCESS_LOGIN_LINK = "login";
|
||||
|
||||
export const CREATE_PASSWORD_EXPIRED_TOKEN =
|
||||
"The invite link has expired. Please try requesting a new invite";
|
||||
export const CREATE_PASSWORD_INVALID_TOKEN =
|
||||
"The invite link is invalid. Please try request a new invite";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
export type OrgRole = {
|
||||
id: string;
|
||||
name: string;
|
||||
isDefault?: boolean;
|
||||
};
|
||||
|
||||
export type Org = {
|
||||
|
|
|
|||
|
|
@ -4,3 +4,7 @@ export type User = {
|
|||
currentOrganizationId: string;
|
||||
organizationIds: string[];
|
||||
};
|
||||
|
||||
export const CurrentUserDetailsRequestPayload = {
|
||||
id: "me",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,4 +25,13 @@ export const FormIcons: {
|
|||
<Icon icon={IconNames.PLUS} color={props.color} iconSize={props.height} />
|
||||
</IconWrapper>
|
||||
),
|
||||
SLASH_ICON: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<Icon
|
||||
icon={IconNames.SLASH}
|
||||
color={props.color}
|
||||
iconSize={props.height}
|
||||
/>
|
||||
</IconWrapper>
|
||||
),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
@import "~@blueprintjs/core/lib/css/blueprint.css";
|
||||
@import "~@blueprintjs/icons/lib/css/blueprint-icons.css";
|
||||
|
||||
@import '../node_modules/@syncfusion/ej2-base/styles/material.css';
|
||||
@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css';
|
||||
@import '../node_modules/@syncfusion/ej2-calendars/styles/material.css';
|
||||
@import '../node_modules/@syncfusion/ej2-dropdowns/styles/material.css';
|
||||
@import '../node_modules/@syncfusion/ej2-inputs/styles/material.css';
|
||||
@import '../node_modules/@syncfusion/ej2-base/styles/material.css';
|
||||
@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css';
|
||||
@import '../node_modules/@syncfusion/ej2-calendars/styles/material.css';
|
||||
@import '../node_modules/@syncfusion/ej2-dropdowns/styles/material.css';
|
||||
@import '../node_modules/@syncfusion/ej2-inputs/styles/material.css';
|
||||
@import '../node_modules/@syncfusion/ej2-navigations/styles/material.css';
|
||||
@import '../node_modules/@syncfusion/ej2-popups/styles/material.css';
|
||||
@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css';
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import moment from "moment-timezone";
|
|||
|
||||
export type JSExecutorGlobal = Record<string, object>;
|
||||
export interface JSExecutor {
|
||||
execute: (src: string, data: JSExecutorGlobal) => string;
|
||||
execute: (src: string, data: JSExecutorGlobal) => any;
|
||||
registerLibrary: (accessor: string, lib: any) => void;
|
||||
unRegisterLibrary: (accessor: string) => void;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ declare let Realm: any;
|
|||
|
||||
export default class RealmExecutor implements JSExecutor {
|
||||
rootRealm: any;
|
||||
creaetSafeObject: any;
|
||||
createSafeObject: any;
|
||||
extrinsics: any[] = [];
|
||||
createSafeFunction: (unsafeFn: Function) => Function;
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ export default class RealmExecutor implements JSExecutor {
|
|||
}
|
||||
})
|
||||
`);
|
||||
this.creaetSafeObject = this.rootRealm.evaluate(`
|
||||
this.createSafeObject = this.rootRealm.evaluate(`
|
||||
(function creaetSafeObject(unsafeObject) {
|
||||
return JSON.parse(JSON.stringify(unsafeObject));
|
||||
})
|
||||
|
|
@ -29,14 +29,23 @@ export default class RealmExecutor implements JSExecutor {
|
|||
unRegisterLibrary(accessor: string) {
|
||||
this.rootRealm.global[accessor] = null;
|
||||
}
|
||||
private convertToMainScope(result: any) {
|
||||
if (typeof result === "object") {
|
||||
if (Array.isArray(result)) {
|
||||
return Object.assign([], result);
|
||||
}
|
||||
return Object.assign({}, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
execute(sourceText: string, data: JSExecutorGlobal) {
|
||||
const safeData = this.creaetSafeObject(data);
|
||||
const safeData = this.createSafeObject(data);
|
||||
let result;
|
||||
try {
|
||||
result = this.rootRealm.evaluate(sourceText, safeData);
|
||||
} catch (e) {
|
||||
//TODO(Satbir): Return an object with an error message.
|
||||
}
|
||||
return result;
|
||||
return this.convertToMainScope(result);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,13 +20,18 @@ const PropertyPaneConfigResponse = {
|
|||
label: "Button Style",
|
||||
controlType: "DROP_DOWN",
|
||||
options: [
|
||||
{ id: "1.2.1", label: "Primary Button", value: "PRIMARY_BUTTON" },
|
||||
{
|
||||
id: "1.2.2",
|
||||
label: "Primary Button",
|
||||
value: "PRIMARY_BUTTON",
|
||||
},
|
||||
{
|
||||
label: "Secondary Button",
|
||||
value: "SECONDARY_BUTTON",
|
||||
},
|
||||
{ id: "1.2.3", label: "Danger Button", value: "DANGER_BUTTON" },
|
||||
{
|
||||
label: "Danger Button",
|
||||
value: "DANGER_BUTTON",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -74,13 +79,28 @@ const PropertyPaneConfigResponse = {
|
|||
label: "Text Style",
|
||||
controlType: "DROP_DOWN",
|
||||
options: [
|
||||
{ id: "3.2.1", label: "Heading", value: "HEADING" },
|
||||
{ id: "3.2.2", label: "Label", value: "LABEL" },
|
||||
{ id: "3.2.3", label: "Body", value: "BODY" },
|
||||
{
|
||||
label: "Heading",
|
||||
value: "HEADING",
|
||||
},
|
||||
{
|
||||
label: "Label",
|
||||
value: "LABEL",
|
||||
},
|
||||
{
|
||||
label: "Body",
|
||||
value: "BODY",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "3.3",
|
||||
propertyName: "allowHtml",
|
||||
label: "Allow HTML",
|
||||
controlType: "SWITCH",
|
||||
},
|
||||
{
|
||||
id: "3.4",
|
||||
propertyName: "isVisible",
|
||||
label: "Visible",
|
||||
controlType: "SWITCH",
|
||||
|
|
@ -97,15 +117,15 @@ const PropertyPaneConfigResponse = {
|
|||
id: "4.1",
|
||||
propertyName: "image",
|
||||
label: "Image",
|
||||
placeholderText: "Enter URL",
|
||||
controlType: "INPUT_TEXT",
|
||||
placeholderText: "Enter URL",
|
||||
},
|
||||
{
|
||||
id: "4.1",
|
||||
propertyName: "defaultImage",
|
||||
label: "Default Image",
|
||||
placeholderText: "Enter URL",
|
||||
controlType: "INPUT_TEXT",
|
||||
placeholderText: "Enter URL",
|
||||
},
|
||||
{
|
||||
id: "4.3",
|
||||
|
|
@ -132,8 +152,8 @@ const PropertyPaneConfigResponse = {
|
|||
propertyName: "label",
|
||||
label: "Label",
|
||||
controlType: "INPUT_TEXT",
|
||||
inputType: "TEXT",
|
||||
placeholderText: "Label the widget",
|
||||
inputType: "TEXT",
|
||||
},
|
||||
{
|
||||
id: "5.2",
|
||||
|
|
@ -141,11 +161,26 @@ const PropertyPaneConfigResponse = {
|
|||
label: "Data Type",
|
||||
controlType: "DROP_DOWN",
|
||||
options: [
|
||||
{ id: "5.2.1", label: "Text", value: "TEXT" },
|
||||
{ id: "5.2.2", label: "Number", value: "NUMBER" },
|
||||
{ id: "5.2.3", label: "Password", value: "PASSWORD" },
|
||||
{ id: "5.2.4", label: "Phone Number", value: "PHONE_NUMBER" },
|
||||
{ id: "5.2.5", label: "Email", value: "EMAIL" },
|
||||
{
|
||||
label: "Text",
|
||||
value: "TEXT",
|
||||
},
|
||||
{
|
||||
label: "Number",
|
||||
value: "NUMBER",
|
||||
},
|
||||
{
|
||||
label: "Password",
|
||||
value: "PASSWORD",
|
||||
},
|
||||
{
|
||||
label: "Phone Number",
|
||||
value: "PHONE_NUMBER",
|
||||
},
|
||||
{
|
||||
label: "Email",
|
||||
value: "EMAIL",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -167,24 +202,24 @@ const PropertyPaneConfigResponse = {
|
|||
propertyName: "maxChars",
|
||||
label: "Max Chars",
|
||||
controlType: "INPUT_TEXT",
|
||||
inputType: "INTEGER",
|
||||
placeholderText: "Enter the max length",
|
||||
inputType: "INTEGER",
|
||||
},
|
||||
{
|
||||
id: "5.6",
|
||||
propertyName: "regex",
|
||||
label: "Regex",
|
||||
controlType: "INPUT_TEXT",
|
||||
inputType: "TEXT",
|
||||
placeholderText: "Enter the regex",
|
||||
inputType: "TEXT",
|
||||
},
|
||||
{
|
||||
id: "5.7",
|
||||
propertyName: "errorMessage",
|
||||
label: "Error Message",
|
||||
controlType: "INPUT_TEXT",
|
||||
inputType: "TEXT",
|
||||
placeholderText: "Enter the message",
|
||||
inputType: "TEXT",
|
||||
},
|
||||
{
|
||||
id: "5.8",
|
||||
|
|
@ -223,8 +258,8 @@ const PropertyPaneConfigResponse = {
|
|||
propertyName: "label",
|
||||
label: "Label",
|
||||
controlType: "INPUT_TEXT",
|
||||
inputType: "TEXT",
|
||||
placeholderText: "Label the widget",
|
||||
inputType: "TEXT",
|
||||
},
|
||||
{
|
||||
id: "6.2",
|
||||
|
|
@ -248,10 +283,10 @@ const PropertyPaneConfigResponse = {
|
|||
},
|
||||
{
|
||||
sectionName: "Actions",
|
||||
id: "5.1.1",
|
||||
id: "6.1.1",
|
||||
children: [
|
||||
{
|
||||
id: "5.1.2",
|
||||
id: "6.1.2",
|
||||
propertyName: "onToggle",
|
||||
label: "onToggle",
|
||||
controlType: "ACTION_SELECTOR",
|
||||
|
|
@ -271,7 +306,7 @@ const PropertyPaneConfigResponse = {
|
|||
controlType: "COLOR_PICKER",
|
||||
},
|
||||
{
|
||||
id: "6.3",
|
||||
id: "7.2",
|
||||
propertyName: "isVisible",
|
||||
label: "Visible",
|
||||
controlType: "SWITCH",
|
||||
|
|
@ -298,36 +333,26 @@ const PropertyPaneConfigResponse = {
|
|||
sectionName: "General",
|
||||
id: "9",
|
||||
children: [
|
||||
// {
|
||||
// id: "9.1",
|
||||
// propertyName: "datePickerType",
|
||||
// label: "Picker Type",
|
||||
// controlType: "DROP_DOWN",
|
||||
// options: [
|
||||
// { label: "Date Picker", value: "DATE_PICKER" },
|
||||
// { label: "Date Range Picker", value: "DATE_RANGE_PICKER" },
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
id: "9.2",
|
||||
propertyName: "label",
|
||||
label: "Label",
|
||||
placeholderText: "Enter Label",
|
||||
controlType: "INPUT_TEXT",
|
||||
placeholderText: "Enter Label",
|
||||
},
|
||||
{
|
||||
id: "9.3",
|
||||
propertyName: "defaultDate",
|
||||
label: "Default Date",
|
||||
placeholderText: "Enter Default Date",
|
||||
controlType: "DATE_PICKER",
|
||||
placeholderText: "Enter Default Date",
|
||||
},
|
||||
{
|
||||
id: "9.5",
|
||||
label: "Timezone",
|
||||
placeholderText: "Select Timezone",
|
||||
propertyName: "timezone",
|
||||
label: "Timezone",
|
||||
controlType: "TIMEZONE_PICKER",
|
||||
placeholderText: "Select Timezone",
|
||||
},
|
||||
{
|
||||
id: "9.6",
|
||||
|
|
@ -373,12 +398,6 @@ const PropertyPaneConfigResponse = {
|
|||
label: "Enter Table Label",
|
||||
controlType: "INPUT_TEXT",
|
||||
},
|
||||
// {
|
||||
// id: "11.2",
|
||||
// propertyName: "tableData",
|
||||
// label: "Enter data array",
|
||||
// controlType: "INPUT_TEXT",
|
||||
// },
|
||||
{
|
||||
id: "11.2",
|
||||
propertyName: "tableData",
|
||||
|
|
@ -410,12 +429,6 @@ const PropertyPaneConfigResponse = {
|
|||
sectionName: "Actions",
|
||||
id: "12",
|
||||
children: [
|
||||
{
|
||||
id: "12.1",
|
||||
propertyName: "tableActions",
|
||||
label: "Record action",
|
||||
controlType: "RECORD_ACTION_SELECTOR",
|
||||
},
|
||||
{
|
||||
id: "12.2",
|
||||
propertyName: "onRowSelected",
|
||||
|
|
@ -442,8 +455,14 @@ const PropertyPaneConfigResponse = {
|
|||
label: "Selection Type",
|
||||
controlType: "DROP_DOWN",
|
||||
options: [
|
||||
{ id: "13.1.1", label: "Single Select", value: "SINGLE_SELECT" },
|
||||
{ id: "13.1.2", label: "Multi Select", value: "MULTI_SELECT" },
|
||||
{
|
||||
label: "Single Select",
|
||||
value: "SINGLE_SELECT",
|
||||
},
|
||||
{
|
||||
label: "Multi Select",
|
||||
value: "MULTI_SELECT",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -579,65 +598,57 @@ const PropertyPaneConfigResponse = {
|
|||
id: "18.1",
|
||||
propertyName: "label",
|
||||
label: "Label",
|
||||
inputType: "INTEGER",
|
||||
placeholderText: "Enter Label",
|
||||
controlType: "INPUT_TEXT",
|
||||
placeholderText: "Enter Label",
|
||||
inputType: "INTEGER",
|
||||
},
|
||||
{
|
||||
id: "18.2",
|
||||
propertyName: "maxNumFiles",
|
||||
label: "No. of files",
|
||||
placeholderText: "Enter No. of files",
|
||||
controlType: "INPUT_TEXT",
|
||||
placeholderText: "Enter No. of files",
|
||||
},
|
||||
{
|
||||
id: "18.3",
|
||||
propertyName: "allowedFileTypes",
|
||||
label: "Allowed File Types",
|
||||
controlType: "MULTI_SELECT",
|
||||
placeholderText: "Enter No. of files",
|
||||
options: [
|
||||
{
|
||||
id: "18.3.1",
|
||||
label: "Any File",
|
||||
value: "*",
|
||||
},
|
||||
{
|
||||
id: "18.3.2",
|
||||
label: "Images",
|
||||
value: "image/*",
|
||||
},
|
||||
{
|
||||
id: "18.3.3",
|
||||
label: "Videos",
|
||||
value: "video/*",
|
||||
},
|
||||
{
|
||||
id: "18.3.4",
|
||||
label: "Audio",
|
||||
value: "audio/*",
|
||||
},
|
||||
{
|
||||
id: "18.3.5",
|
||||
label: "Text",
|
||||
value: "text/*",
|
||||
},
|
||||
{
|
||||
id: "18.3.6",
|
||||
label: "JPEG",
|
||||
value: "image/jpeg",
|
||||
},
|
||||
{
|
||||
id: "18.3.7",
|
||||
label: "PNG",
|
||||
value: "*.png",
|
||||
},
|
||||
{
|
||||
id: "18.3.8",
|
||||
label: "GIF",
|
||||
value: "*.gif",
|
||||
},
|
||||
],
|
||||
controlType: "MULTI_SELECT",
|
||||
},
|
||||
{
|
||||
id: "18.4",
|
||||
|
|
@ -649,7 +660,7 @@ const PropertyPaneConfigResponse = {
|
|||
},
|
||||
],
|
||||
},
|
||||
configVersion: 1,
|
||||
name: "propertyPane",
|
||||
};
|
||||
|
||||
export default PropertyPaneConfigResponse;
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ import DynamicTextField from "components/editorComponents/form/fields/DynamicTex
|
|||
import DropdownField from "components/editorComponents/form/fields/DropdownField";
|
||||
import DatasourcesField from "components/editorComponents/form/fields/DatasourcesField";
|
||||
import KeyValueFieldArray from "components/editorComponents/form/fields/KeyValueFieldArray";
|
||||
import JSONEditorField from "components/editorComponents/form/fields/JSONEditorField";
|
||||
import ApiResponseView from "components/editorComponents/ApiResponseView";
|
||||
import { API_EDITOR_FORM_NAME } from "constants/forms";
|
||||
import LoadingOverlayScreen from "components/editorComponents/LoadingOverlayScreen";
|
||||
import { FormIcons } from "icons/FormIcons";
|
||||
|
||||
const Form = styled.form`
|
||||
display: flex;
|
||||
|
|
@ -65,8 +65,6 @@ const ActionButton = styled(BaseButton)`
|
|||
|
||||
const JSONEditorFieldWrapper = styled.div`
|
||||
margin: 5px;
|
||||
border: 1px solid #d0d7dd;
|
||||
border-radius: 4px;
|
||||
`;
|
||||
|
||||
const DatasourceWrapper = styled.div`
|
||||
|
|
@ -107,7 +105,11 @@ const ApiEditorForm: React.FC<Props> = (props: Props) => {
|
|||
{isSaving && <LoadingOverlayScreen>Saving...</LoadingOverlayScreen>}
|
||||
<MainConfiguration>
|
||||
<FormRow>
|
||||
<TextField name="name" placeholder="API Name *" showError />
|
||||
<TextField
|
||||
name="name"
|
||||
placeholder="API name (camel case)"
|
||||
showError
|
||||
/>
|
||||
<ActionButtons>
|
||||
<ActionButton
|
||||
text="Delete"
|
||||
|
|
@ -141,10 +143,9 @@ const ApiEditorForm: React.FC<Props> = (props: Props) => {
|
|||
<DatasourcesField name="datasource.id" pluginId={pluginId} />
|
||||
</DatasourceWrapper>
|
||||
<DynamicTextField
|
||||
placeholder="API Path"
|
||||
placeholder="v1/method"
|
||||
name="actionConfiguration.path"
|
||||
leftIcon="slash"
|
||||
showError
|
||||
leftIcon={FormIcons.SLASH_ICON}
|
||||
/>
|
||||
</FormRow>
|
||||
</MainConfiguration>
|
||||
|
|
@ -162,7 +163,12 @@ const ApiEditorForm: React.FC<Props> = (props: Props) => {
|
|||
<React.Fragment>
|
||||
<FormLabel>{"Post Body"}</FormLabel>
|
||||
<JSONEditorFieldWrapper>
|
||||
<JSONEditorField name="actionConfiguration.body" />
|
||||
<DynamicTextField
|
||||
name="actionConfiguration.body"
|
||||
height={300}
|
||||
showLineNumbers
|
||||
allowTabIndent
|
||||
/>
|
||||
</JSONEditorFieldWrapper>
|
||||
</React.Fragment>
|
||||
)}
|
||||
|
|
|
|||
219
app/client/src/pages/UserAuth/CreatePassword.tsx
Normal file
219
app/client/src/pages/UserAuth/CreatePassword.tsx
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
import React, { useLayoutEffect } from "react";
|
||||
import { AppState } from "reducers";
|
||||
import { Link, withRouter, RouteComponentProps } from "react-router-dom";
|
||||
import { connect } from "react-redux";
|
||||
import { InjectedFormProps, reduxForm, Field } from "redux-form";
|
||||
import { CREATE_PASSWORD_FORM_NAME } from "constants/forms";
|
||||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
import { getIsTokenValid, getIsValidatingToken } from "selectors/authSelectors";
|
||||
import { Icon } from "@blueprintjs/core";
|
||||
import TextField from "components/editorComponents/form/fields/TextField";
|
||||
import FormMessage, {
|
||||
FormMessageProps,
|
||||
MessageAction,
|
||||
} from "components/editorComponents/form/FormMessage";
|
||||
import Spinner from "components/editorComponents/Spinner";
|
||||
import FormButton from "components/editorComponents/FormButton";
|
||||
import FormGroup from "components/editorComponents/form/FormGroup";
|
||||
import StyledForm from "components/editorComponents/Form";
|
||||
import { isEmptyString, isStrongPassword } from "utils/formhelpers";
|
||||
|
||||
import {
|
||||
CreatePasswordFormValues,
|
||||
createPasswordSubmitHandler,
|
||||
} from "./helpers";
|
||||
import {
|
||||
AuthCardHeader,
|
||||
AuthCardFooter,
|
||||
AuthCardContainer,
|
||||
AuthCardBody,
|
||||
AuthCardNavLink,
|
||||
FormActions,
|
||||
} from "./StyledComponents";
|
||||
import { AUTH_LOGIN_URL } from "constants/routes";
|
||||
|
||||
import {
|
||||
CREATE_PASSWORD_PAGE_PASSWORD_INPUT_LABEL,
|
||||
CREATE_PASSWORD_PAGE_PASSWORD_INPUT_PLACEHOLDER,
|
||||
CREATE_PASSWORD_LOGIN_LINK_TEXT,
|
||||
CREATE_PASSWORD_SUBMIT_BUTTON_TEXT,
|
||||
CREATE_PASSWORD_PAGE_SUBTITLE,
|
||||
CREATE_PASSWORD_PAGE_TITLE,
|
||||
FORM_VALIDATION_INVALID_PASSWORD,
|
||||
FORM_VALIDATION_EMPTY_PASSWORD,
|
||||
CREATE_PASSWORD_EXPIRED_TOKEN,
|
||||
CREATE_PASSWORD_INVALID_TOKEN,
|
||||
CREATE_PASSWORD_RESET_SUCCESS,
|
||||
CREATE_PASSWORD_RESET_SUCCESS_LOGIN_LINK,
|
||||
PRIVACY_POLICY_LINK,
|
||||
TERMS_AND_CONDITIONS_LINK,
|
||||
} from "constants/messages";
|
||||
|
||||
const validate = (values: CreatePasswordFormValues) => {
|
||||
const errors: CreatePasswordFormValues = {};
|
||||
if (!values.password || isEmptyString(values.password)) {
|
||||
errors.password = FORM_VALIDATION_EMPTY_PASSWORD;
|
||||
} else if (!isStrongPassword(values.password)) {
|
||||
errors.password = FORM_VALIDATION_INVALID_PASSWORD;
|
||||
}
|
||||
return errors;
|
||||
};
|
||||
|
||||
type CreatePasswordProps = InjectedFormProps<
|
||||
CreatePasswordFormValues,
|
||||
{
|
||||
verifyToken: (token: string, email: string) => void;
|
||||
isTokenValid: boolean;
|
||||
validatingToken: boolean;
|
||||
}
|
||||
> & {
|
||||
verifyToken: (token: string, email: string) => void;
|
||||
isTokenValid: boolean;
|
||||
validatingToken: boolean;
|
||||
} & RouteComponentProps<{ email: string; token: string }>;
|
||||
|
||||
export const CreatePassword = (props: CreatePasswordProps) => {
|
||||
const {
|
||||
error,
|
||||
handleSubmit,
|
||||
pristine,
|
||||
submitting,
|
||||
submitSucceeded,
|
||||
submitFailed,
|
||||
initialValues,
|
||||
isTokenValid,
|
||||
validatingToken,
|
||||
verifyToken,
|
||||
valid,
|
||||
} = props;
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (initialValues.token && initialValues.email)
|
||||
verifyToken(initialValues.token, initialValues.email);
|
||||
}, [initialValues.token, initialValues.email, verifyToken]);
|
||||
|
||||
const showInvalidMessage = !initialValues.token || !initialValues.email;
|
||||
const showExpiredMessage = !isTokenValid && !validatingToken;
|
||||
const showSuccessMessage = submitSucceeded && !pristine;
|
||||
const showFailureMessage = submitFailed && !!error;
|
||||
|
||||
let message = "";
|
||||
let messageActions: MessageAction[] | undefined = undefined;
|
||||
|
||||
if (showExpiredMessage) {
|
||||
message = CREATE_PASSWORD_EXPIRED_TOKEN;
|
||||
}
|
||||
if (showInvalidMessage) {
|
||||
message = CREATE_PASSWORD_INVALID_TOKEN;
|
||||
}
|
||||
|
||||
if (showSuccessMessage) {
|
||||
message = CREATE_PASSWORD_RESET_SUCCESS;
|
||||
messageActions = [
|
||||
{
|
||||
url: AUTH_LOGIN_URL,
|
||||
text: CREATE_PASSWORD_RESET_SUCCESS_LOGIN_LINK,
|
||||
intent: "success",
|
||||
},
|
||||
];
|
||||
}
|
||||
if (showFailureMessage) {
|
||||
message = error;
|
||||
}
|
||||
|
||||
const messageTagProps: FormMessageProps = {
|
||||
intent:
|
||||
showInvalidMessage || showExpiredMessage || showFailureMessage
|
||||
? "danger"
|
||||
: "success",
|
||||
message,
|
||||
actions: messageActions,
|
||||
};
|
||||
|
||||
if (showInvalidMessage || showExpiredMessage) {
|
||||
return <FormMessage {...messageTagProps} />;
|
||||
}
|
||||
|
||||
if (!isTokenValid && validatingToken) {
|
||||
return <Spinner />;
|
||||
}
|
||||
return (
|
||||
<AuthCardContainer>
|
||||
{(showSuccessMessage || showFailureMessage) && (
|
||||
<FormMessage {...messageTagProps} />
|
||||
)}
|
||||
<AuthCardHeader>
|
||||
<h1>{CREATE_PASSWORD_PAGE_TITLE}</h1>
|
||||
<h5>{CREATE_PASSWORD_PAGE_SUBTITLE}</h5>
|
||||
</AuthCardHeader>
|
||||
<AuthCardBody>
|
||||
<StyledForm onSubmit={handleSubmit(createPasswordSubmitHandler)}>
|
||||
<FormGroup
|
||||
intent={error ? "danger" : "none"}
|
||||
label={CREATE_PASSWORD_PAGE_PASSWORD_INPUT_LABEL}
|
||||
>
|
||||
<TextField
|
||||
name="password"
|
||||
type="password"
|
||||
placeholder={CREATE_PASSWORD_PAGE_PASSWORD_INPUT_PLACEHOLDER}
|
||||
showError
|
||||
/>
|
||||
</FormGroup>
|
||||
<Field type="hidden" name="email" component="input" />
|
||||
<Field type="hidden" name="token" component="input" />
|
||||
<FormActions>
|
||||
<FormButton
|
||||
type="submit"
|
||||
text={CREATE_PASSWORD_SUBMIT_BUTTON_TEXT}
|
||||
intent="primary"
|
||||
disabled={pristine || !valid}
|
||||
loading={submitting}
|
||||
/>
|
||||
</FormActions>
|
||||
</StyledForm>
|
||||
</AuthCardBody>
|
||||
<AuthCardNavLink to={AUTH_LOGIN_URL}>
|
||||
{CREATE_PASSWORD_LOGIN_LINK_TEXT}
|
||||
<Icon icon="arrow-right" intent="primary" />
|
||||
</AuthCardNavLink>
|
||||
<AuthCardFooter>
|
||||
<Link to="#">{PRIVACY_POLICY_LINK}</Link>
|
||||
<Link to="#">{TERMS_AND_CONDITIONS_LINK}</Link>
|
||||
</AuthCardFooter>
|
||||
</AuthCardContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(
|
||||
(state: AppState, props: CreatePasswordProps) => {
|
||||
const queryParams = new URLSearchParams(props.location.search);
|
||||
return {
|
||||
initialValues: {
|
||||
email: queryParams.get("email") || undefined,
|
||||
token: queryParams.get("token") || undefined,
|
||||
},
|
||||
isTokenValid: getIsTokenValid(state),
|
||||
validatingToken: getIsValidatingToken(state),
|
||||
};
|
||||
},
|
||||
(dispatch: any) => ({
|
||||
verifyToken: (token: string, email: string) =>
|
||||
dispatch({
|
||||
type: ReduxActionTypes.VERIFY_INVITE_INIT,
|
||||
payload: { token, email },
|
||||
}),
|
||||
}),
|
||||
)(
|
||||
reduxForm<
|
||||
CreatePasswordFormValues,
|
||||
{
|
||||
verifyToken: (token: string, email: string) => void;
|
||||
validatingToken: boolean;
|
||||
isTokenValid: boolean;
|
||||
}
|
||||
>({
|
||||
validate,
|
||||
form: CREATE_PASSWORD_FORM_NAME,
|
||||
touchOnBlur: true,
|
||||
})(withRouter(CreatePassword)),
|
||||
);
|
||||
|
|
@ -3,7 +3,11 @@ import { Link, useLocation } from "react-router-dom";
|
|||
import { connect } from "react-redux";
|
||||
import { InjectedFormProps, reduxForm, formValueSelector } from "redux-form";
|
||||
import { Icon } from "@blueprintjs/core";
|
||||
import { LOGIN_FORM_NAME } from "constants/forms";
|
||||
import {
|
||||
LOGIN_FORM_NAME,
|
||||
LOGIN_FORM_EMAIL_FIELD_NAME,
|
||||
LOGIN_FORM_PASSWORD_FIELD_NAME,
|
||||
} from "constants/forms";
|
||||
import { getAppsmithConfigs } from "configs";
|
||||
import { FORGOT_PASSWORD_URL, SIGN_UP_URL } from "constants/routes";
|
||||
import { LOGIN_SUBMIT_PATH } from "constants/ApiConstants";
|
||||
|
|
@ -47,15 +51,17 @@ import {
|
|||
|
||||
const validate = (values: LoginFormValues) => {
|
||||
const errors: LoginFormValues = {};
|
||||
if (!values.password || isEmptyString(values.password)) {
|
||||
errors.password = FORM_VALIDATION_EMPTY_PASSWORD;
|
||||
} else if (!isStrongPassword(values.password)) {
|
||||
errors.password = FORM_VALIDATION_INVALID_PASSWORD;
|
||||
const email = values[LOGIN_FORM_EMAIL_FIELD_NAME];
|
||||
const password = values[LOGIN_FORM_PASSWORD_FIELD_NAME];
|
||||
if (!password || isEmptyString(password)) {
|
||||
errors[LOGIN_FORM_PASSWORD_FIELD_NAME] = FORM_VALIDATION_EMPTY_PASSWORD;
|
||||
} else if (!isStrongPassword(password)) {
|
||||
errors[LOGIN_FORM_PASSWORD_FIELD_NAME] = FORM_VALIDATION_INVALID_PASSWORD;
|
||||
}
|
||||
if (!values.username || isEmptyString(values.username)) {
|
||||
errors.username = FORM_VALIDATION_EMPTY_EMAIL;
|
||||
} else if (!isEmail(values.username)) {
|
||||
errors.username = FORM_VALIDATION_INVALID_EMAIL;
|
||||
if (!email || isEmptyString(email)) {
|
||||
errors[LOGIN_FORM_EMAIL_FIELD_NAME] = FORM_VALIDATION_EMPTY_EMAIL;
|
||||
} else if (!isEmail(email)) {
|
||||
errors[LOGIN_FORM_EMAIL_FIELD_NAME] = FORM_VALIDATION_INVALID_EMAIL;
|
||||
}
|
||||
return errors;
|
||||
};
|
||||
|
|
@ -66,7 +72,7 @@ type LoginFormProps = { emailValue: string } & InjectedFormProps<
|
|||
>;
|
||||
|
||||
export const Login = (props: LoginFormProps) => {
|
||||
const { error, pristine } = props;
|
||||
const { error, pristine, valid } = props;
|
||||
const location = useLocation();
|
||||
|
||||
const queryParams = new URLSearchParams(location.search);
|
||||
|
|
@ -108,7 +114,7 @@ export const Login = (props: LoginFormProps) => {
|
|||
label={LOGIN_PAGE_EMAIL_INPUT_LABEL}
|
||||
>
|
||||
<TextField
|
||||
name="username"
|
||||
name={LOGIN_FORM_EMAIL_FIELD_NAME}
|
||||
type="email"
|
||||
placeholder={LOGIN_PAGE_EMAIL_INPUT_PLACEHOLDER}
|
||||
showError
|
||||
|
|
@ -120,7 +126,7 @@ export const Login = (props: LoginFormProps) => {
|
|||
>
|
||||
<TextField
|
||||
type="password"
|
||||
name="password"
|
||||
name={LOGIN_FORM_PASSWORD_FIELD_NAME}
|
||||
placeholder={LOGIN_PAGE_PASSWORD_INPUT_PLACEHOLDER}
|
||||
showError
|
||||
/>
|
||||
|
|
@ -129,6 +135,7 @@ export const Login = (props: LoginFormProps) => {
|
|||
<FormActions>
|
||||
<FormButton
|
||||
type="submit"
|
||||
disabled={pristine || !valid}
|
||||
text={LOGIN_PAGE_LOGIN_BUTTON_TEXT}
|
||||
intent="primary"
|
||||
/>
|
||||
|
|
@ -153,7 +160,7 @@ export const Login = (props: LoginFormProps) => {
|
|||
|
||||
const selector = formValueSelector(LOGIN_FORM_NAME);
|
||||
export default connect(state => ({
|
||||
emailValue: selector(state, "email"),
|
||||
emailValue: selector(state, LOGIN_FORM_EMAIL_FIELD_NAME),
|
||||
}))(
|
||||
reduxForm<LoginFormValues, { emailValue: string }>({
|
||||
validate,
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ export const SignUp = (props: InjectedFormProps<SignupFormValues>) => {
|
|||
submitFailed,
|
||||
submitSucceeded,
|
||||
pristine,
|
||||
valid,
|
||||
} = props;
|
||||
return (
|
||||
<AuthCardContainer>
|
||||
|
|
@ -113,7 +114,7 @@ export const SignUp = (props: InjectedFormProps<SignupFormValues>) => {
|
|||
<FormActions>
|
||||
<FormButton
|
||||
type="submit"
|
||||
disabled={pristine}
|
||||
disabled={pristine || !valid}
|
||||
loading={submitting}
|
||||
text={SIGNUP_PAGE_SUBMIT_BUTTON_TEXT}
|
||||
intent="primary"
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ export type ResetPasswordFormValues = {
|
|||
email?: string;
|
||||
};
|
||||
|
||||
export type CreatePasswordFormValues = ResetPasswordFormValues;
|
||||
|
||||
export type ForgotPasswordFormValues = {
|
||||
email?: string;
|
||||
};
|
||||
|
|
@ -64,6 +66,27 @@ export const resetPasswordSubmitHandler = (
|
|||
});
|
||||
};
|
||||
|
||||
export const createPasswordSubmitHandler = (
|
||||
values: CreatePasswordFormValues,
|
||||
dispatch: any,
|
||||
): Promise<any> => {
|
||||
const { token, email, password } = values;
|
||||
return new Promise((resolve, reject) => {
|
||||
dispatch({
|
||||
type: ReduxActionTypes.INVITED_USER_SIGNUP_INIT,
|
||||
payload: {
|
||||
resolve,
|
||||
reject,
|
||||
token,
|
||||
email,
|
||||
password,
|
||||
},
|
||||
});
|
||||
}).catch(error => {
|
||||
throw new SubmissionError(error);
|
||||
});
|
||||
};
|
||||
|
||||
export const forgotPasswordSubmitHandler = (
|
||||
values: ForgotPasswordFormValues,
|
||||
dispatch: any,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { AuthContainer, AuthCard } from "./StyledComponents";
|
|||
import SignUp from "./SignUp";
|
||||
import ForgotPassword from "./ForgotPassword";
|
||||
import ResetPassword from "./ResetPassword";
|
||||
import CreatePassword from "./CreatePassword";
|
||||
|
||||
export const UserAuth = () => {
|
||||
const { path } = useRouteMatch();
|
||||
|
|
@ -31,6 +32,11 @@ export const UserAuth = () => {
|
|||
path={`${path}/forgotPassword`}
|
||||
component={ForgotPassword}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`${path}/createPassword`}
|
||||
component={CreatePassword}
|
||||
/>
|
||||
</Switch>
|
||||
</CSSTransition>
|
||||
</TransitionGroup>
|
||||
|
|
|
|||
|
|
@ -60,6 +60,9 @@ export const options = (
|
|||
{
|
||||
content: <Link to="/org/settings">Organization Settings</Link>,
|
||||
},
|
||||
{
|
||||
content: <Link to="/applications">Applications</Link>,
|
||||
},
|
||||
{
|
||||
content: <Link to="/org/users">Members</Link>,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2,19 +2,14 @@ import React from "react";
|
|||
import { Route } from "react-router-dom";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { useSelector } from "store";
|
||||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
import { hasAuthExpired } from "utils/storage";
|
||||
import { User } from "constants/userConstants";
|
||||
import { setCurrentUserDetails } from "actions/userActions";
|
||||
|
||||
export const checkAuth = (dispatch: any, currentUser?: User) => {
|
||||
return hasAuthExpired().then(hasExpired => {
|
||||
if (!currentUser || hasExpired) {
|
||||
dispatch({
|
||||
type: ReduxActionTypes.SET_CURRENT_USER_INIT,
|
||||
payload: {
|
||||
id: "me",
|
||||
},
|
||||
});
|
||||
dispatch(setCurrentUserDetails());
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useLayoutEffect } from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import styled from "styled-components";
|
||||
import { useHistory } from "react-router-dom";
|
||||
|
|
@ -37,7 +37,7 @@ import FormGroup from "components/editorComponents/form/FormGroup";
|
|||
import SelectField from "components/editorComponents/form/fields/SelectField";
|
||||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
import { AppState } from "reducers";
|
||||
import { getRoles } from "selectors/organizationSelectors";
|
||||
import { getRoles, getDefaultRole } from "selectors/organizationSelectors";
|
||||
import { OrgRole } from "constants/orgConstants";
|
||||
import { isEmail } from "utils/formhelpers";
|
||||
|
||||
|
|
@ -110,9 +110,10 @@ const StyledInviteFieldGroup = styled.div`
|
|||
const renderInviteUsersByRoleForm = (
|
||||
renderer: WrappedFieldArrayProps<InviteUsersToOrgByRoleValues> & {
|
||||
roles?: OrgRole[];
|
||||
role?: OrgRole;
|
||||
},
|
||||
) => {
|
||||
const { fields, roles } = renderer;
|
||||
const { fields, roles, role } = renderer;
|
||||
return (
|
||||
<React.Fragment>
|
||||
{fields.map((field, index) => {
|
||||
|
|
@ -148,7 +149,12 @@ const renderInviteUsersByRoleForm = (
|
|||
);
|
||||
})}
|
||||
<FormActionButton
|
||||
onClick={() => fields.push({ id: generateReactKey() })}
|
||||
onClick={() =>
|
||||
fields.push({
|
||||
id: generateReactKey(),
|
||||
role: !!role ? role.id : undefined,
|
||||
})
|
||||
}
|
||||
text={INVITE_USERS_ADD_EMAIL_LIST_FIELD}
|
||||
large
|
||||
icon="plus"
|
||||
|
|
@ -162,10 +168,12 @@ type InviteUsersFormProps = InjectedFormProps<
|
|||
{
|
||||
fetchRoles: () => void;
|
||||
roles?: OrgRole[];
|
||||
defaultRole?: OrgRole;
|
||||
}
|
||||
> & {
|
||||
fetchRoles: () => void;
|
||||
roles?: OrgRole[];
|
||||
defaultRole?: OrgRole;
|
||||
};
|
||||
|
||||
export const InviteUsersForm = (props: InviteUsersFormProps) => {
|
||||
|
|
@ -177,13 +185,27 @@ export const InviteUsersForm = (props: InviteUsersFormProps) => {
|
|||
error,
|
||||
fetchRoles,
|
||||
roles,
|
||||
initialize,
|
||||
defaultRole,
|
||||
pristine,
|
||||
} = props;
|
||||
const history = useHistory();
|
||||
useLayoutEffect(() => {
|
||||
|
||||
useEffect(() => {
|
||||
if (!roles) {
|
||||
fetchRoles();
|
||||
} else {
|
||||
initialize({
|
||||
usersByRole: [
|
||||
{
|
||||
id: generateReactKey(),
|
||||
role: !!defaultRole ? defaultRole.id : undefined,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}, [fetchRoles, roles]);
|
||||
}, [fetchRoles, roles, defaultRole, initialize]);
|
||||
|
||||
return (
|
||||
<StyledForm>
|
||||
{submitSucceeded && (
|
||||
|
|
@ -210,6 +232,7 @@ export const InviteUsersForm = (props: InviteUsersFormProps) => {
|
|||
<FormFooter
|
||||
divider
|
||||
onSubmit={handleSubmit(inviteUsersToOrgSubmitHandler)}
|
||||
canSubmit={!pristine}
|
||||
submitting={submitting && !submitFailed}
|
||||
onCancel={() => history.goBack()}
|
||||
submitOnEnter={false}
|
||||
|
|
@ -223,6 +246,7 @@ export default connect(
|
|||
(state: AppState) => {
|
||||
return {
|
||||
roles: getRoles(state),
|
||||
defaultRole: getDefaultRole(state),
|
||||
};
|
||||
},
|
||||
(dispatch: any) => ({
|
||||
|
|
@ -231,16 +255,9 @@ export default connect(
|
|||
)(
|
||||
reduxForm<
|
||||
InviteUsersToOrgFormValues,
|
||||
{ fetchRoles: () => void; roles?: OrgRole[] }
|
||||
{ fetchRoles: () => void; roles?: OrgRole[]; defaultRole?: OrgRole }
|
||||
>({
|
||||
form: INVITE_USERS_TO_ORG_FORM,
|
||||
validate,
|
||||
initialValues: {
|
||||
usersByRole: [
|
||||
{
|
||||
id: generateReactKey(),
|
||||
},
|
||||
],
|
||||
},
|
||||
})(InviteUsersForm),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,18 @@ const authReducer = createReducer(initialState, {
|
|||
isValidatingToken: false,
|
||||
isTokenValid: false,
|
||||
}),
|
||||
[ReduxActionTypes.VERIFY_INVITE_INIT]: () => ({
|
||||
isTokenValid: false,
|
||||
isValidatingToken: true,
|
||||
}),
|
||||
[ReduxActionTypes.VERIFY_INVITE_SUCCESS]: () => ({
|
||||
isValidatingToken: false,
|
||||
isTokenValid: true,
|
||||
}),
|
||||
[ReduxActionErrorTypes.VERIFY_INVITE_ERROR]: () => ({
|
||||
isValidatingToken: false,
|
||||
isTokenValid: false,
|
||||
}),
|
||||
});
|
||||
|
||||
export interface AuthState {
|
||||
|
|
|
|||
|
|
@ -34,11 +34,12 @@ import {
|
|||
createActionSuccess,
|
||||
deleteActionSuccess,
|
||||
FetchActionsPayload,
|
||||
runApiAction,
|
||||
updateActionSuccess,
|
||||
} from "actions/actionActions";
|
||||
import {
|
||||
evaluateDynamicBoundValue,
|
||||
getDynamicBindings,
|
||||
getDynamicValue,
|
||||
isDynamicValue,
|
||||
} from "utils/DynamicBindingUtils";
|
||||
import { validateResponse } from "./ErrorSagas";
|
||||
|
|
@ -83,7 +84,7 @@ const createActionErrorResponse = (
|
|||
|
||||
export function* evaluateDynamicBoundValueSaga(path: string): any {
|
||||
const nameBindingsWithData = yield select(getNameBindingsWithData);
|
||||
return evaluateDynamicBoundValue(nameBindingsWithData, path);
|
||||
return getDynamicValue(`{{${path}}}`, nameBindingsWithData);
|
||||
}
|
||||
|
||||
export function* getActionParams(jsonPathKeys: string[] | undefined) {
|
||||
|
|
@ -97,7 +98,9 @@ export function* getActionParams(jsonPathKeys: string[] | undefined) {
|
|||
);
|
||||
const dynamicBindings: Record<string, string> = {};
|
||||
jsonPathKeys.forEach((key, i) => {
|
||||
dynamicBindings[key] = values[i];
|
||||
let value = values[i];
|
||||
if (typeof value === "object") value = JSON.stringify(value);
|
||||
dynamicBindings[key] = value;
|
||||
});
|
||||
return mapToPropList(dynamicBindings);
|
||||
}
|
||||
|
|
@ -303,6 +306,7 @@ export function* updateActionSaga(
|
|||
intent: Intent.SUCCESS,
|
||||
});
|
||||
yield put(updateActionSuccess({ data: response.data }));
|
||||
yield put(runApiAction(data.id));
|
||||
}
|
||||
} catch (error) {
|
||||
yield put({
|
||||
|
|
@ -344,8 +348,9 @@ export function* runApiActionSaga(action: ReduxAction<string>) {
|
|||
getFormData,
|
||||
API_EDITOR_FORM_NAME,
|
||||
);
|
||||
const actionObject: PageAction = yield select(getAction, values.id);
|
||||
let action: ExecuteActionRequest["action"] = { id: values.id };
|
||||
let jsonPathKeys = values.jsonPathKeys;
|
||||
let jsonPathKeys = actionObject.jsonPathKeys;
|
||||
if (!valid) {
|
||||
console.error("Form error");
|
||||
return;
|
||||
|
|
@ -356,7 +361,7 @@ export function* runApiActionSaga(action: ReduxAction<string>) {
|
|||
if (isDynamicValue(actionString)) {
|
||||
const { paths } = getDynamicBindings(actionString);
|
||||
// Replace cause the existing keys could have been updated
|
||||
jsonPathKeys = paths;
|
||||
jsonPathKeys = paths.filter(path => !!path);
|
||||
} else {
|
||||
jsonPathKeys = [];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,9 +88,9 @@ function* syncApiParamsSaga(
|
|||
}
|
||||
} else if (field.includes("actionConfiguration.queryParameters")) {
|
||||
const { values } = yield select(getFormData, API_EDITOR_FORM_NAME);
|
||||
const path = values.actionConfiguration.path;
|
||||
const path = values.actionConfiguration.path || "";
|
||||
const pathHasParams = path.indexOf("?") > -1;
|
||||
const currentPath = values.actionConfiguration.path.substring(
|
||||
const currentPath = path.substring(
|
||||
0,
|
||||
pathHasParams ? path.indexOf("?") : undefined,
|
||||
);
|
||||
|
|
@ -127,14 +127,16 @@ function* changeApiSaga(actionPayload: ReduxAction<{ id: string }>) {
|
|||
const data = _.isEmpty(draft) ? action : draft;
|
||||
yield put(initialize(API_EDITOR_FORM_NAME, data));
|
||||
history.push(API_EDITOR_ID_URL(applicationId, pageId, id));
|
||||
// Sync the api params my mocking a change action
|
||||
yield call(syncApiParamsSaga, {
|
||||
type: ReduxFormActionTypes.ARRAY_REMOVE,
|
||||
payload: data.actionConfiguration.queryParameters,
|
||||
meta: {
|
||||
field: "actionConfiguration.queryParameters",
|
||||
},
|
||||
});
|
||||
if (data.actionConfiguration && data.actionConfiguration.queryParameters) {
|
||||
// Sync the api params my mocking a change action
|
||||
yield call(syncApiParamsSaga, {
|
||||
type: ReduxFormActionTypes.ARRAY_REMOVE,
|
||||
payload: data.actionConfiguration.queryParameters,
|
||||
meta: {
|
||||
field: "actionConfiguration.queryParameters",
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function* updateDraftsSaga() {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { call, takeLatest, put, all } from "redux-saga/effects";
|
||||
import {
|
||||
ReduxAction,
|
||||
ReduxActionWithPromise,
|
||||
ReduxActionTypes,
|
||||
ReduxActionErrorTypes,
|
||||
} from "constants/ReduxActionConstants";
|
||||
|
|
@ -8,8 +9,8 @@ import UserApi, {
|
|||
CreateUserRequest,
|
||||
CreateUserResponse,
|
||||
ForgotPasswordRequest,
|
||||
ResetPasswordRequest,
|
||||
ResetPasswordVerifyTokenRequest,
|
||||
VerifyTokenRequest,
|
||||
TokenPasswordUpdateRequest,
|
||||
FetchUserRequest,
|
||||
FetchUserResponse,
|
||||
} from "api/UserApi";
|
||||
|
|
@ -23,14 +24,18 @@ import {
|
|||
import { fetchOrgsSaga } from "./OrgSagas";
|
||||
|
||||
import { resetAuthExpiration } from "utils/storage";
|
||||
import {
|
||||
logoutUserSuccess,
|
||||
fetchCurrentUser,
|
||||
logoutUserError,
|
||||
verifyInviteSuccess,
|
||||
verifyInviteError,
|
||||
invitedUserSignupError,
|
||||
invitedUserSignupSuccess,
|
||||
} from "actions/userActions";
|
||||
|
||||
export function* createUserSaga(
|
||||
action: ReduxAction<{
|
||||
resolve: any;
|
||||
reject: any;
|
||||
email: string;
|
||||
password: string;
|
||||
}>,
|
||||
action: ReduxActionWithPromise<CreateUserRequest>,
|
||||
) {
|
||||
const { email, password, resolve, reject } = action.payload;
|
||||
try {
|
||||
|
|
@ -68,7 +73,7 @@ export function* createUserSaga(
|
|||
}
|
||||
|
||||
export function* forgotPasswordSaga(
|
||||
action: ReduxAction<{ resolve: any; reject: any; email: string }>,
|
||||
action: ReduxActionWithPromise<ForgotPasswordRequest>,
|
||||
) {
|
||||
const { email, resolve, reject } = action.payload;
|
||||
|
||||
|
|
@ -98,21 +103,13 @@ export function* forgotPasswordSaga(
|
|||
}
|
||||
|
||||
export function* resetPasswordSaga(
|
||||
action: ReduxAction<{
|
||||
resolve: any;
|
||||
reject: any;
|
||||
email: string;
|
||||
token: string;
|
||||
password: string;
|
||||
}>,
|
||||
action: ReduxActionWithPromise<TokenPasswordUpdateRequest>,
|
||||
) {
|
||||
const { email, token, password, resolve, reject } = action.payload;
|
||||
try {
|
||||
const request: ResetPasswordRequest = {
|
||||
user: {
|
||||
email,
|
||||
password,
|
||||
},
|
||||
const request: TokenPasswordUpdateRequest = {
|
||||
email,
|
||||
password,
|
||||
token,
|
||||
};
|
||||
const response: ApiResponse = yield callAPI(UserApi.resetPassword, request);
|
||||
|
|
@ -137,6 +134,32 @@ export function* resetPasswordSaga(
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function* invitedUserSignupSaga(
|
||||
action: ReduxActionWithPromise<TokenPasswordUpdateRequest>,
|
||||
) {
|
||||
const { email, token, password, resolve, reject } = action.payload;
|
||||
try {
|
||||
const request: TokenPasswordUpdateRequest = { email, password, token };
|
||||
const response: ApiResponse = yield callAPI(
|
||||
UserApi.confirmInvitedUserSignup,
|
||||
request,
|
||||
);
|
||||
const isValidResponse = yield validateResponse(response);
|
||||
if (!isValidResponse) {
|
||||
const errorMessage = yield getResponseErrorMessage(response);
|
||||
yield call(reject, { _error: errorMessage });
|
||||
} else {
|
||||
yield put(invitedUserSignupSuccess());
|
||||
yield call(resolve);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
yield call(reject, { _error: error.message });
|
||||
yield put(invitedUserSignupError(error));
|
||||
}
|
||||
}
|
||||
|
||||
type InviteUserPayload = {
|
||||
email: string;
|
||||
groupIds: string[];
|
||||
|
|
@ -154,10 +177,8 @@ export function* inviteUser(payload: InviteUserPayload, reject: any) {
|
|||
}
|
||||
|
||||
export function* inviteUsers(
|
||||
action: ReduxAction<{
|
||||
action: ReduxActionWithPromise<{
|
||||
data: Array<{ roleId: string; emails: string[] }>;
|
||||
resolve: any;
|
||||
reject: any;
|
||||
}>,
|
||||
) {
|
||||
try {
|
||||
|
|
@ -200,11 +221,11 @@ export function* inviteUsers(
|
|||
}
|
||||
|
||||
export function* verifyResetPasswordTokenSaga(
|
||||
action: ReduxAction<{ token: string; email: string }>,
|
||||
action: ReduxAction<VerifyTokenRequest>,
|
||||
) {
|
||||
try {
|
||||
const request: ResetPasswordVerifyTokenRequest = action.payload;
|
||||
const response: ApiResponse = yield callAPI(
|
||||
const request: VerifyTokenRequest = action.payload;
|
||||
const response: ApiResponse = yield call(
|
||||
UserApi.verifyResetPasswordToken,
|
||||
request,
|
||||
);
|
||||
|
|
@ -222,6 +243,20 @@ export function* verifyResetPasswordTokenSaga(
|
|||
}
|
||||
}
|
||||
|
||||
export function* verifyUserInviteSaga(action: ReduxAction<VerifyTokenRequest>) {
|
||||
try {
|
||||
const request: VerifyTokenRequest = action.payload;
|
||||
const response: ApiResponse = yield call(UserApi.verifyUserInvite, request);
|
||||
const isValidResponse = yield validateResponse(response);
|
||||
if (isValidResponse) {
|
||||
yield put(verifyInviteSuccess());
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
yield put(verifyInviteError(error));
|
||||
}
|
||||
}
|
||||
|
||||
export function* fetchUserSaga(action: ReduxAction<FetchUserRequest>) {
|
||||
try {
|
||||
const request: FetchUserRequest = action.payload;
|
||||
|
|
@ -255,6 +290,20 @@ export function* setCurrentUserSaga(action: ReduxAction<FetchUserRequest>) {
|
|||
}
|
||||
}
|
||||
|
||||
export function* logoutSaga() {
|
||||
try {
|
||||
const response: ApiResponse = yield call(UserApi.logoutUser);
|
||||
const isValidResponse = yield validateResponse(response);
|
||||
if (isValidResponse) {
|
||||
yield put(logoutUserSuccess());
|
||||
yield put(fetchCurrentUser());
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
yield put(logoutUserError(error));
|
||||
}
|
||||
}
|
||||
|
||||
export default function* userSagas() {
|
||||
yield all([
|
||||
takeLatest(ReduxActionTypes.CREATE_USER_INIT, createUserSaga),
|
||||
|
|
@ -267,5 +316,11 @@ export default function* userSagas() {
|
|||
takeLatest(ReduxActionTypes.INVITE_USERS_TO_ORG_INIT, inviteUsers),
|
||||
takeLatest(ReduxActionTypes.FETCH_USER_INIT, fetchUserSaga),
|
||||
takeLatest(ReduxActionTypes.SET_CURRENT_USER_INIT, setCurrentUserSaga),
|
||||
takeLatest(ReduxActionTypes.LOGOUT_USER_INIT, logoutSaga),
|
||||
takeLatest(ReduxActionTypes.VERIFY_INVITE_INIT, verifyUserInviteSaga),
|
||||
takeLatest(
|
||||
ReduxActionTypes.INVITED_USER_SIGNUP_INIT,
|
||||
invitedUserSignupSaga,
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { AppState, DataTree } from "reducers";
|
||||
import { ActionDataState } from "reducers/entityReducers/actionsReducer";
|
||||
|
||||
export const getDataTree = (state: AppState): DataTree => state.entities;
|
||||
|
||||
|
|
@ -15,3 +16,6 @@ export const getPluginIdOfName = (
|
|||
if (!plugin) return undefined;
|
||||
return plugin.id;
|
||||
};
|
||||
|
||||
export const getActions = (state: AppState): ActionDataState["data"] =>
|
||||
state.entities.actions.data;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { getFormValues, isDirty, isValid } from "redux-form";
|
||||
import { getFormValues, isValid } from "redux-form";
|
||||
import { AppState } from "reducers";
|
||||
import { RestAction } from "api/ActionAPI";
|
||||
|
||||
type GetFormData = (
|
||||
state: AppState,
|
||||
|
|
@ -7,8 +8,9 @@ type GetFormData = (
|
|||
) => { values: object; dirty: boolean; valid: boolean };
|
||||
|
||||
export const getFormData: GetFormData = (state, formName) => {
|
||||
const values = getFormValues(formName)(state);
|
||||
const dirty = isDirty(formName)(state);
|
||||
const values = getFormValues(formName)(state) as RestAction;
|
||||
const drafts = state.ui.apiPane.drafts;
|
||||
const dirty = values.id in drafts;
|
||||
const valid = isValid(formName)(state);
|
||||
return { values, dirty, valid };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import { DataTree } from "reducers";
|
||||
import { AppState, DataTree } from "reducers";
|
||||
import { JSONPath } from "jsonpath-plus";
|
||||
import { createSelector } from "reselect";
|
||||
import { getDataTree } from "./entitiesSelector";
|
||||
import { getActions, getDataTree } from "./entitiesSelector";
|
||||
import { ActionDataState } from "reducers/entityReducers/actionsReducer";
|
||||
import createCachedSelector from "re-reselect";
|
||||
|
||||
export type NameBindingsWithData = Record<string, object>;
|
||||
export const getNameBindingsWithData = createSelector(
|
||||
|
|
@ -22,3 +24,25 @@ export const getNameBindingsWithData = createSelector(
|
|||
return nameBindingsWithData;
|
||||
},
|
||||
);
|
||||
|
||||
// For autocomplete. Use actions cached responses if
|
||||
// there isn't a response already
|
||||
export const getNameBindingsForAutocomplete = createCachedSelector(
|
||||
getNameBindingsWithData,
|
||||
getActions,
|
||||
(namedBindings: NameBindingsWithData, actions: ActionDataState["data"]) => {
|
||||
const cachedResponses: Record<string, any> = {};
|
||||
if (actions && actions.length) {
|
||||
actions.forEach(action => {
|
||||
if (!(action.name in namedBindings) && action.cacheResponse) {
|
||||
try {
|
||||
cachedResponses[action.name] = JSON.parse(action.cacheResponse);
|
||||
} catch (e) {
|
||||
cachedResponses[action.name] = action.cacheResponse;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return { ...namedBindings, ...cachedResponses };
|
||||
},
|
||||
)((state: AppState) => state.entities.actions.data.length);
|
||||
|
|
|
|||
|
|
@ -20,3 +20,7 @@ export const getCurrentOrg = createSelector(
|
|||
export const getRoles = (state: AppState): OrgRole[] | undefined => {
|
||||
return state.ui.orgs.roles;
|
||||
};
|
||||
|
||||
export const getDefaultRole = (state: AppState): OrgRole | undefined => {
|
||||
return state.ui.orgs.roles?.find(role => role.isDefault);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,25 +1,10 @@
|
|||
import _ from "lodash";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
import {
|
||||
DATA_BIND_AUTOCOMPLETE,
|
||||
DATA_BIND_REGEX,
|
||||
} from "constants/BindingsConstants";
|
||||
import { DATA_BIND_REGEX } from "constants/BindingsConstants";
|
||||
import ValidationFactory from "./ValidationFactory";
|
||||
import JSExecutionManagerSingleton from "jsExecution/JSExecutionManagerSingleton";
|
||||
import { NameBindingsWithData } from "selectors/nameBindingsWithDataSelector";
|
||||
|
||||
export const isDynamicAutocompleteMatch = (value: string): boolean =>
|
||||
DATA_BIND_AUTOCOMPLETE.test(value);
|
||||
|
||||
export const getDynamicAutocompleteSearchTerm = (value: string): string => {
|
||||
const bindings = value.match(DATA_BIND_AUTOCOMPLETE) || [];
|
||||
if (bindings.length > 0) {
|
||||
return bindings[2];
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
export const isDynamicValue = (value: string): boolean =>
|
||||
DATA_BIND_REGEX.test(value);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ class TextWidget extends BaseWidget<TextWidgetProps, WidgetState> {
|
|||
widgetId={this.props.widgetId}
|
||||
key={this.props.widgetId}
|
||||
textStyle={this.props.textStyle}
|
||||
allowHtml={this.props.allowHtml}
|
||||
text={this.props.text}
|
||||
isLoading={this.props.isLoading}
|
||||
/>
|
||||
|
|
@ -36,6 +37,7 @@ export interface TextWidgetProps extends WidgetProps {
|
|||
text?: string;
|
||||
textStyle: TextStyle;
|
||||
isLoading: boolean;
|
||||
allowHtml: boolean;
|
||||
}
|
||||
|
||||
export default TextWidget;
|
||||
|
|
|
|||
|
|
@ -2246,9 +2246,9 @@
|
|||
"@babel/types" "^7.3.0"
|
||||
|
||||
"@types/chance@^1.0.7":
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/chance/-/chance-1.0.7.tgz#c680a3891a505d8c626ec3a46bb1c0496419dfb6"
|
||||
integrity sha512-LBOkJ7899SSLm08KicLYX3DqWUhfDspMLWNGuV1UPpL3iUENSvI0THGlf05n9yNHTR7zDlV/mCGZ7ZJ0ws8v3Q==
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/chance/-/chance-1.0.8.tgz#48e0a5648f54487a9128915fe090154fb1a2f348"
|
||||
integrity sha512-S1VWROFGexiUYyBFsP0NRjp6PkJ4rKECQ3HQJ0cJKW/2BcNyas9lXATRdnTNnN4CsICjEXTltAalAo8dJQQLKg==
|
||||
|
||||
"@types/codemirror@^0.0.82":
|
||||
version "0.0.82"
|
||||
|
|
@ -2340,16 +2340,16 @@
|
|||
"@types/istanbul-lib-report" "*"
|
||||
|
||||
"@types/jest@^24.0.22":
|
||||
version "24.0.24"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.24.tgz#0f2f523dc77cc1bc6bef34eaf287ede887a73f05"
|
||||
integrity sha512-vgaG968EDPSJPMunEDdZvZgvxYSmeH8wKqBlHSkBt1pV2XlLEVDzsj1ZhLuI4iG4Pv841tES61txSBF0obh4CQ==
|
||||
version "24.0.25"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.25.tgz#2aba377824ce040114aa906ad2cac2c85351360f"
|
||||
integrity sha512-hnP1WpjN4KbGEK4dLayul6lgtys6FPz0UfxMeMQCv0M+sTnzN3ConfiO72jHgLxl119guHgI8gLqDOrRLsyp2g==
|
||||
dependencies:
|
||||
jest-diff "^24.3.0"
|
||||
|
||||
"@types/json-schema@^7.0.3":
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636"
|
||||
integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==
|
||||
version "7.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339"
|
||||
integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==
|
||||
|
||||
"@types/lodash@^4.14.120":
|
||||
version "4.14.149"
|
||||
|
|
@ -2376,14 +2376,14 @@
|
|||
"@types/node" "*"
|
||||
|
||||
"@types/node@*":
|
||||
version "12.12.21"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.21.tgz#aa44a6363291c7037111c47e4661ad210aded23f"
|
||||
integrity sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA==
|
||||
version "13.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.1.2.tgz#fe94285bf5e0782e1a9e5a8c482b1c34465fa385"
|
||||
integrity sha512-B8emQA1qeKerqd1dmIsQYnXi+mmAzTB7flExjmy5X1aVAKFNNNDubkavwR13kR6JnpeLp3aLoJhwn9trWPAyFQ==
|
||||
|
||||
"@types/node@^10.12.18":
|
||||
version "10.17.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.11.tgz#46ba035fb917b31c948280dbea22ab8838f386a4"
|
||||
integrity sha512-dNd2pp8qTzzNLAs3O8nH3iU9DG9866KHq9L3ISPB7DOGERZN81nW/5/g/KzMJpCU8jrbCiMRBzV9/sCEdRosig==
|
||||
version "10.17.13"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.13.tgz#ccebcdb990bd6139cd16e84c39dc2fb1023ca90c"
|
||||
integrity sha512-pMCcqU2zT4TjqYFrWtYHKal7Sl30Ims6ulZ4UFXxI4xbtQqK/qqKwkDoBFCfooRqqmRu9vY3xaJRwxSh673aYg==
|
||||
|
||||
"@types/normalize-package-data@^2.4.0":
|
||||
version "2.4.0"
|
||||
|
|
@ -2435,9 +2435,9 @@
|
|||
"@types/react" "*"
|
||||
|
||||
"@types/react-native@*":
|
||||
version "0.60.25"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.60.25.tgz#65cb0bf5dd0631079215b63525458e4123c1c90e"
|
||||
integrity sha512-827dIVvSTxSH5uTpsJJH7O4wpRuw0rm3yIzRL3a2yKawA0nyhgC1GPKTXHFIn2GfSdXn1Gty2dJ+k6uDZF3MWQ==
|
||||
version "0.60.27"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.60.27.tgz#d6313256f3cf9a685bd8885efddb86b85b9a4820"
|
||||
integrity sha512-W8YrhnnHBwybruJp57enWc9dP9G7okcQkm88TMPZZKMVNiJIZj17q/rruMLuuuER+SaGrYjhO+BA3MpfkiTaSQ==
|
||||
dependencies:
|
||||
"@types/prop-types" "*"
|
||||
"@types/react" "*"
|
||||
|
|
@ -2596,9 +2596,9 @@
|
|||
source-map "^0.6.1"
|
||||
|
||||
"@types/webpack@^4.41.0":
|
||||
version "4.41.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.0.tgz#b813a044d8b0dec7dfcd7622fdbe327bde06eb9a"
|
||||
integrity sha512-tWkdf9nO0zFgAY/EumUKwrDUhraHKDqCPhwfFR/R8l0qnPdgb9le0Gzhvb7uzVpouuDGBgiE//ZdY+5jcZy2TA==
|
||||
version "4.41.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.1.tgz#571f0e137ce698710dd2637f7d222811eb83e274"
|
||||
integrity sha512-n9fP8UrMxOi1wiM3oM+vMZHMJJ7WoQohqd63C20cmKOFkNEy9Q8hyZyDR6PWdvSYt3V3A7cwDq/kWxHlRYYZEg==
|
||||
dependencies:
|
||||
"@types/anymatch" "*"
|
||||
"@types/node" "*"
|
||||
|
|
@ -2613,46 +2613,46 @@
|
|||
integrity sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==
|
||||
|
||||
"@types/yargs@^13.0.0":
|
||||
version "13.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.3.tgz#76482af3981d4412d65371a318f992d33464a380"
|
||||
integrity sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ==
|
||||
version "13.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.4.tgz#53d231cebe1a540e7e13727fc1f0d13ad4a9ba3b"
|
||||
integrity sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==
|
||||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^2.0.0", "@typescript-eslint/eslint-plugin@^2.8.0":
|
||||
version "2.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.12.0.tgz#0da7cbca7b24f4c6919e9eb31c704bfb126f90ad"
|
||||
integrity sha512-1t4r9rpLuEwl3hgt90jY18wJHSyb0E3orVL3DaqwmpiSDHmHiSspVsvsFF78BJ/3NNG3qmeso836jpuBWYziAA==
|
||||
version "2.14.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.14.0.tgz#c74447400537d4eb7aae1e31879ab43e6c662a8a"
|
||||
integrity sha512-sneOJ3Hu0m5whJiVIxGBZZZMxMJ7c0LhAJzeMJgHo+n5wFs+/6rSR/gl7crkdR2kNwfOOSdzdc0gMvatG4dX2Q==
|
||||
dependencies:
|
||||
"@typescript-eslint/experimental-utils" "2.12.0"
|
||||
"@typescript-eslint/experimental-utils" "2.14.0"
|
||||
eslint-utils "^1.4.3"
|
||||
functional-red-black-tree "^1.0.1"
|
||||
regexpp "^3.0.0"
|
||||
tsutils "^3.17.1"
|
||||
|
||||
"@typescript-eslint/experimental-utils@2.12.0":
|
||||
version "2.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.12.0.tgz#e0a76ffb6293e058748408a191921e453c31d40d"
|
||||
integrity sha512-jv4gYpw5N5BrWF3ntROvCuLe1IjRenLy5+U57J24NbPGwZFAjhnM45qpq0nDH1y/AZMb3Br25YiNVwyPbz6RkA==
|
||||
"@typescript-eslint/experimental-utils@2.14.0":
|
||||
version "2.14.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.14.0.tgz#e9179fa3c44e00b3106b85d7b69342901fb43e3b"
|
||||
integrity sha512-KcyKS7G6IWnIgl3ZpyxyBCxhkBPV+0a5Jjy2g5HxlrbG2ZLQNFeneIBVXdaBCYOVjvGmGGFKom1kgiAY75SDeQ==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.3"
|
||||
"@typescript-eslint/typescript-estree" "2.12.0"
|
||||
"@typescript-eslint/typescript-estree" "2.14.0"
|
||||
eslint-scope "^5.0.0"
|
||||
|
||||
"@typescript-eslint/parser@^2.0.0", "@typescript-eslint/parser@^2.8.0":
|
||||
version "2.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.12.0.tgz#393f1604943a4ca570bb1a45bc8834e9b9158884"
|
||||
integrity sha512-lPdkwpdzxEfjI8TyTzZqPatkrswLSVu4bqUgnB03fHSOwpC7KSerPgJRgIAf11UGNf7HKjJV6oaPZI4AghLU6g==
|
||||
version "2.14.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.14.0.tgz#30fa0523d86d74172a5e32274558404ba4262cd6"
|
||||
integrity sha512-haS+8D35fUydIs+zdSf4BxpOartb/DjrZ2IxQ5sR8zyGfd77uT9ZJZYF8+I0WPhzqHmfafUBx8MYpcp8pfaoSA==
|
||||
dependencies:
|
||||
"@types/eslint-visitor-keys" "^1.0.0"
|
||||
"@typescript-eslint/experimental-utils" "2.12.0"
|
||||
"@typescript-eslint/typescript-estree" "2.12.0"
|
||||
"@typescript-eslint/experimental-utils" "2.14.0"
|
||||
"@typescript-eslint/typescript-estree" "2.14.0"
|
||||
eslint-visitor-keys "^1.1.0"
|
||||
|
||||
"@typescript-eslint/typescript-estree@2.12.0":
|
||||
version "2.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.12.0.tgz#bd9e547ccffd17dfab0c3ab0947c80c8e2eb914c"
|
||||
integrity sha512-rGehVfjHEn8Frh9UW02ZZIfJs6SIIxIu/K1bbci8rFfDE/1lQ8krIJy5OXOV3DVnNdDPtoiPOdEANkLMrwXbiQ==
|
||||
"@typescript-eslint/typescript-estree@2.14.0":
|
||||
version "2.14.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.14.0.tgz#c67698acdc14547f095eeefe908958d93e1a648d"
|
||||
integrity sha512-pnLpUcMNG7GfFFfNQbEX6f1aPa5fMnH2G9By+A1yovYI4VIOK2DzkaRuUlIkbagpAcrxQHLqovI1YWqEcXyRnA==
|
||||
dependencies:
|
||||
debug "^4.1.1"
|
||||
eslint-visitor-keys "^1.1.0"
|
||||
|
|
@ -3184,9 +3184,9 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1:
|
|||
color-convert "^1.9.0"
|
||||
|
||||
ansi-styles@^4.0.0, ansi-styles@^4.1.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.0.tgz#5681f0dcf7ae5880a7841d8831c4724ed9cc0172"
|
||||
integrity sha512-7kFQgnEaMdRtwf6uSfUnVr9gSGC7faurn+J/Mv90/W+iTtN0405/nLdopfMWwchyxhbGYl6TC4Sccn9TUkGAgg==
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359"
|
||||
integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==
|
||||
dependencies:
|
||||
"@types/color-name" "^1.1.1"
|
||||
color-convert "^2.0.1"
|
||||
|
|
@ -3452,7 +3452,7 @@ asynckit@^0.4.0:
|
|||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
|
||||
|
||||
atob@^2.1.1:
|
||||
atob@^2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
||||
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
|
||||
|
|
@ -4174,13 +4174,13 @@ browserslist@4.7.3:
|
|||
node-releases "^1.1.40"
|
||||
|
||||
browserslist@^4.0.0, browserslist@^4.6.0, browserslist@^4.6.2, browserslist@^4.6.4, browserslist@^4.8.0, browserslist@^4.8.2:
|
||||
version "4.8.2"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.2.tgz#b45720ad5fbc8713b7253c20766f701c9a694289"
|
||||
integrity sha512-+M4oeaTplPm/f1pXDw84YohEv7B1i/2Aisei8s4s6k3QsoSHa7i5sz8u/cGQkkatCPxMASKxPualR4wwYgVboA==
|
||||
version "4.8.3"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.3.tgz#65802fcd77177c878e015f0e3189f2c4f627ba44"
|
||||
integrity sha512-iU43cMMknxG1ClEZ2MDKeonKE1CCrFVkQK2AqO2YWFmvIrx4JWrvQ4w4hQez6EpVI8rHTtqh/ruHHDHSOKxvUg==
|
||||
dependencies:
|
||||
caniuse-lite "^1.0.30001015"
|
||||
caniuse-lite "^1.0.30001017"
|
||||
electron-to-chromium "^1.3.322"
|
||||
node-releases "^1.1.42"
|
||||
node-releases "^1.1.44"
|
||||
|
||||
bser@2.1.1:
|
||||
version "2.1.1"
|
||||
|
|
@ -4395,10 +4395,10 @@ caniuse-api@^3.0.0:
|
|||
lodash.memoize "^4.1.2"
|
||||
lodash.uniq "^4.5.0"
|
||||
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001010, caniuse-lite@^1.0.30001012, caniuse-lite@^1.0.30001015:
|
||||
version "1.0.30001016"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001016.tgz#16ea48d7d6e8caf3cad3295c2d746fe38c4e7f66"
|
||||
integrity sha512-yYQ2QfotceRiH4U+h1Us86WJXtVHDmy3nEKIdYPsZCYnOV5/tMgGbmoIlrMzmh2VXlproqYtVaKeGDBkMZifFA==
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001010, caniuse-lite@^1.0.30001012, caniuse-lite@^1.0.30001017:
|
||||
version "1.0.30001017"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001017.tgz#d3ad6ec18148b9bd991829958d9d7e562bb78cd6"
|
||||
integrity sha512-EDnZyOJ6eYh6lHmCvCdHAFbfV4KJ9lSdfv4h/ppEhrU/Yudkl7jujwMZ1we6RX7DXqBfT04pVMQ4J+1wcTlsKA==
|
||||
|
||||
capture-exit@^2.0.0:
|
||||
version "2.0.0"
|
||||
|
|
@ -4695,9 +4695,9 @@ code-point-at@^1.0.0:
|
|||
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
|
||||
|
||||
codemirror@^5.50.0:
|
||||
version "5.50.0"
|
||||
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.50.0.tgz#aeacd18f225735b17cbab98908edace87fedcdab"
|
||||
integrity sha512-32LAmGcBNhKtJP4WGgkcaCVQDyChAyaWA6jasg778ziZzo3PWBuhpAQIJMO8//Id45RoaLyXjuhcRUBoS8Vg+Q==
|
||||
version "5.50.2"
|
||||
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.50.2.tgz#32ddfe2b50193fcf573d8141c4a31d267c92b4a3"
|
||||
integrity sha512-PPjUsC1oXSM86lunKrw609P1oM0Wu8z9rqzjbeyBYCcx44VL41aUpccdOf1PfAZtTONlmN3sT3p2etLNYa1OGg==
|
||||
|
||||
collapse-white-space@^1.0.0, collapse-white-space@^1.0.2:
|
||||
version "1.0.5"
|
||||
|
|
@ -4940,17 +4940,17 @@ copy-to-clipboard@^3.0.8:
|
|||
toggle-selection "^1.0.6"
|
||||
|
||||
core-js-compat@^3.1.1, core-js-compat@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.0.tgz#4eb6cb69d03d99159ed7c860cd5fcf7d23a62ea9"
|
||||
integrity sha512-Z3eCNjGgoYluH89Jt4wVkfYsc/VdLrA2/woX5lm0isO/pCT+P+Y+o65bOuEnjDJLthdwTBxbCVzptTXtc18fJg==
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.1.tgz#39638c935c83c93a793abb628b252ec43e85783a"
|
||||
integrity sha512-2Tl1EuxZo94QS2VeH28Ebf5g3xbPZG/hj/N5HDDy4XMP/ImR0JIer/nggQRiMN91Q54JVkGbytf42wO29oXVHg==
|
||||
dependencies:
|
||||
browserslist "^4.8.2"
|
||||
semver "7.0.0"
|
||||
|
||||
core-js-pure@^3.0.0, core-js-pure@^3.0.1:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.0.tgz#c86e14d9316659af04dd54266addc9271f6164f8"
|
||||
integrity sha512-+YSSo7UFDFuVvMUr1HVFYArb22pYIKRDISBo6V50kRuS0MsXgsuDWmJYFu6dJsJupr77S486xRnDkr/BWQQonw==
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.1.tgz#59acfb71caf2fb495aae4c1a0b2a7f2c1b65267e"
|
||||
integrity sha512-yKiUdvQWq66xUc408duxUCxFHuDfz5trF5V4xnQzb8C7P/5v2gFUdyNWQoevyAeGYB1hl1X/pzGZ20R3WxZQBA==
|
||||
|
||||
core-js@^1.0.0:
|
||||
version "1.2.7"
|
||||
|
|
@ -4963,9 +4963,9 @@ core-js@^2.4.0:
|
|||
integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==
|
||||
|
||||
core-js@^3.0.1, core-js@^3.0.4, core-js@^3.4.1:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.0.tgz#2b854e451de1967d1e29896025cdc13a2518d9ea"
|
||||
integrity sha512-AHPTNKzyB+YwgDWoSOCaid9PUSEF6781vsfiK8qUz62zRR448/XgK2NtCbpiUGizbep8Lrpt0Du19PpGGZvw3Q==
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.1.tgz#39d5e2e346258cc01eb7d44345b1c3c014ca3f05"
|
||||
integrity sha512-186WjSik2iTGfDjfdCZAxv2ormxtKgemjC3SI6PL31qOA0j5LhTDVjHChccoc7brwLvpvLPiMyRlcO88C4l1QQ==
|
||||
|
||||
core-util-is@1.0.2, core-util-is@~1.0.0:
|
||||
version "1.0.2"
|
||||
|
|
@ -5370,9 +5370,9 @@ cyclist@^1.0.1:
|
|||
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
|
||||
|
||||
cypress@^3.7.0:
|
||||
version "3.8.0"
|
||||
resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.8.0.tgz#7d4cd08f81f9048ee36760cc9ee3b9014f9e84ab"
|
||||
integrity sha512-gtEbqCgKETRc3pQFMsELRgIBNgiQg7vbOWTrCi7WE7bgOwNCaW9PEX8Jb3UN8z/maIp9WwzoFfeySfelYY7nRA==
|
||||
version "3.8.1"
|
||||
resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.8.1.tgz#7821084e0ead81d35ffa29f2141c977dfdfc2343"
|
||||
integrity sha512-eLk5OpL/ZMDfQx9t7ZaDUAGVcvSOPTi7CG1tiUnu9BGk7caBiDhuFi3Tz/D5vWqH/Dl6Uh4X+Au4W+zh0xzbXw==
|
||||
dependencies:
|
||||
"@cypress/listr-verbose-renderer" "0.4.1"
|
||||
"@cypress/xvfb" "1.2.4"
|
||||
|
|
@ -6079,9 +6079,9 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1
|
|||
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
||||
|
||||
escodegen@^1.11.0, escodegen@^1.9.1:
|
||||
version "1.12.0"
|
||||
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.0.tgz#f763daf840af172bb3a2b6dd7219c0e17f7ff541"
|
||||
integrity sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==
|
||||
version "1.12.1"
|
||||
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.1.tgz#08770602a74ac34c7a90ca9229e7d51e379abc76"
|
||||
integrity sha512-Q8t2YZ+0e0pc7NRVj3B4tSQ9rim1oi4Fh46k2xhJ2qOiEwhQfdjyEQddWdj7ZFaKmU+5104vn1qrcjEPWq+bgQ==
|
||||
dependencies:
|
||||
esprima "^3.1.3"
|
||||
estraverse "^4.2.0"
|
||||
|
|
@ -6091,9 +6091,9 @@ escodegen@^1.11.0, escodegen@^1.9.1:
|
|||
source-map "~0.6.1"
|
||||
|
||||
eslint-config-prettier@^6.1.0:
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.7.0.tgz#9a876952e12df2b284adbd3440994bf1f39dfbb9"
|
||||
integrity sha512-FamQVKM3jjUVwhG4hEMnbtsq7xOIDm+SY5iBPfR8gKsJoAB2IQnNF+bk1+8Fy44Nq7PPJaLvkRxILYdJWoguKQ==
|
||||
version "6.9.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.9.0.tgz#430d24822e82f7deb1e22a435bfa3999fae4ad64"
|
||||
integrity sha512-k4E14HBtcLv0uqThaI6I/n1LEqROp8XaPu6SO9Z32u5NlGRC07Enu1Bh2KEFw4FNHbekH8yzbIU9kUGxbiGmCA==
|
||||
dependencies:
|
||||
get-stdin "^6.0.0"
|
||||
|
||||
|
|
@ -8020,6 +8020,15 @@ internal-ip@^4.3.0:
|
|||
default-gateway "^4.2.0"
|
||||
ipaddr.js "^1.9.0"
|
||||
|
||||
internal-slot@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.2.tgz#9c2e9fb3cd8e5e4256c6f45fe310067fcfa378a3"
|
||||
integrity sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==
|
||||
dependencies:
|
||||
es-abstract "^1.17.0-next.1"
|
||||
has "^1.0.3"
|
||||
side-channel "^1.0.2"
|
||||
|
||||
interpret@^1.0.0, interpret@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296"
|
||||
|
|
@ -10309,10 +10318,10 @@ node-notifier@^5.4.2:
|
|||
shellwords "^0.1.1"
|
||||
which "^1.3.0"
|
||||
|
||||
node-releases@^1.1.29, node-releases@^1.1.40, node-releases@^1.1.42:
|
||||
version "1.1.43"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.43.tgz#2c6ca237f88ce11d49631f11190bb01f8d0549f2"
|
||||
integrity sha512-Rmfnj52WNhvr83MvuAWHEqXVoZXCcDQssSOffU4n4XOL9sPrP61mSZ88g25NqmABDvH7PiAlFCzoSCSdzA293w==
|
||||
node-releases@^1.1.29, node-releases@^1.1.40, node-releases@^1.1.44:
|
||||
version "1.1.44"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.44.tgz#cd66438a6eb875e3eb012b6a12e48d9f4326ffd7"
|
||||
integrity sha512-NwbdvJyR7nrcGrXvKAvzc5raj/NkoJudkarh2yIpJ4t0NH4aqjUDz/486P+ynIW5eokKOfzGNRdYoLfBlomruw==
|
||||
dependencies:
|
||||
semver "^6.3.0"
|
||||
|
||||
|
|
@ -10738,9 +10747,9 @@ p-limit@^1.1.0:
|
|||
p-try "^1.0.0"
|
||||
|
||||
p-limit@^2.0.0, p-limit@^2.2.0:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537"
|
||||
integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==
|
||||
version "2.2.2"
|
||||
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e"
|
||||
integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==
|
||||
dependencies:
|
||||
p-try "^2.0.0"
|
||||
|
||||
|
|
@ -11807,9 +11816,9 @@ postcss@7.0.21:
|
|||
supports-color "^6.1.0"
|
||||
|
||||
postcss@^7, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.23, postcss@^7.0.5, postcss@^7.0.6:
|
||||
version "7.0.25"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.25.tgz#dd2a2a753d50b13bed7a2009b4a18ac14d9db21e"
|
||||
integrity sha512-NXXVvWq9icrm/TgQC0O6YVFi4StfJz46M1iNd/h6B26Nvh/HKI+q4YZtFN/EjcInZliEscO/WL10BXnc1E5nwg==
|
||||
version "7.0.26"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.26.tgz#5ed615cfcab35ba9bbb82414a4fa88ea10429587"
|
||||
integrity sha512-IY4oRjpXWYshuTDFxMVkJDtWIk2LhsTlu8bZnbEJA4+bYT16Lvpo8Qv6EvDumhYRgzjZl489pmsY3qVgJQ08nA==
|
||||
dependencies:
|
||||
chalk "^2.4.2"
|
||||
source-map "^0.6.1"
|
||||
|
|
@ -11984,9 +11993,9 @@ pseudomap@^1.0.2:
|
|||
integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
|
||||
|
||||
psl@^1.1.24, psl@^1.1.28:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.6.0.tgz#60557582ee23b6c43719d9890fb4170ecd91e110"
|
||||
integrity sha512-SYKKmVel98NCOYXpkwUqZqh0ahZeeKfmisiLIcEZdsb+WbLv02g/dI5BUmZnIyOe7RzZtLax81nnb2HbvC2tzA==
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c"
|
||||
integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==
|
||||
|
||||
public-encrypt@^4.0.0:
|
||||
version "4.0.3"
|
||||
|
|
@ -12298,9 +12307,9 @@ react-docgen-typescript-loader@^3.6.0:
|
|||
react-docgen-typescript "^1.15.0"
|
||||
|
||||
react-docgen-typescript@^1.15.0:
|
||||
version "1.16.1"
|
||||
resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-1.16.1.tgz#3c4570601b2e765280adf570a0f344b35111604d"
|
||||
integrity sha512-r2FyrOa9ynupwKzufHn8IqhWt8aYts3TZz/LWzJGFMyH8AaHQ/Z4LY+fbaI5Gs46DmeyNJvzg2dDELV2k/bL0A==
|
||||
version "1.16.2"
|
||||
resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-1.16.2.tgz#d5f26ba6591ac4bc61628c514d492de461ae7c2c"
|
||||
integrity sha512-nECrg2qih81AKp0smkxXebF72/2EjmEn7gXSlWLDHLbpGcbw2yIorol24fw1FWqvndIY82sfSd0x/SyfMKY1Jw==
|
||||
|
||||
react-docgen@^4.1.1:
|
||||
version "4.1.1"
|
||||
|
|
@ -12855,9 +12864,9 @@ redux-saga@^1.1.3:
|
|||
"@redux-saga/core" "^1.1.3"
|
||||
|
||||
"redux@^3.6.0 || ^4.0.0", redux@^4.0.0, redux@^4.0.1, redux@^4.0.4:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.4.tgz#4ee1aeb164b63d6a1bcc57ae4aa0b6e6fa7a3796"
|
||||
integrity sha512-vKv4WdiJxOWKxK0yRoaK3Y4pxxB0ilzVx6dszU2W8wLxlb2yikRph4iV/ymtdJ6ZxpBLFbyrxklnT5yBbQSl3Q==
|
||||
version "4.0.5"
|
||||
resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f"
|
||||
integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==
|
||||
dependencies:
|
||||
loose-envify "^1.4.0"
|
||||
symbol-observable "^1.2.0"
|
||||
|
|
@ -12918,7 +12927,7 @@ regex-parser@2.2.10:
|
|||
resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.10.tgz#9e66a8f73d89a107616e63b39d4deddfee912b37"
|
||||
integrity sha512-8t6074A68gHfU8Neftl0Le6KTDwfGAj7IyjPIMSfikI2wJUTHDMaIq42bUsfVnj8mhx0R+45rdUXHGpN164avA==
|
||||
|
||||
regexp.prototype.flags@^1.2.0:
|
||||
regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75"
|
||||
integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==
|
||||
|
|
@ -13319,9 +13328,9 @@ rxjs@^5.0.0-beta.11:
|
|||
symbol-observable "1.0.1"
|
||||
|
||||
rxjs@^6.3.3, rxjs@^6.4.0, rxjs@^6.5.3:
|
||||
version "6.5.3"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a"
|
||||
integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==
|
||||
version "6.5.4"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c"
|
||||
integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
|
|
@ -13654,6 +13663,14 @@ shellwords@^0.1.1:
|
|||
resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
|
||||
integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==
|
||||
|
||||
side-channel@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.2.tgz#df5d1abadb4e4bf4af1cd8852bf132d2f7876947"
|
||||
integrity sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA==
|
||||
dependencies:
|
||||
es-abstract "^1.17.0-next.1"
|
||||
object-inspect "^1.7.0"
|
||||
|
||||
signal-exit@^3.0.0, signal-exit@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
|
||||
|
|
@ -13783,9 +13800,9 @@ source-list-map@^2.0.0:
|
|||
integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
|
||||
|
||||
source-map-explorer@^2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/source-map-explorer/-/source-map-explorer-2.1.2.tgz#305d61efbb1d1ebbf24a9fffef718635054d509c"
|
||||
integrity sha512-rgujHHHwf0/HCSTFbdTPJETGTgbGqVDD068Ob/wfV41u3AdU8iknSvGTDoU8vCIUeZuLnHX4JYsQ1RMd129XCQ==
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map-explorer/-/source-map-explorer-2.2.1.tgz#4bd236a1fe73e8b9db475f60197c48fc041928b8"
|
||||
integrity sha512-vfjS5IRaENgXtTq2Bym0ctEorYGYNHLVCVZZeL1fvkD5iBoWKMlUhF/oFBTcTn9cxry1flplyvk0QGTROafB3Q==
|
||||
dependencies:
|
||||
btoa "^1.2.1"
|
||||
chalk "^3.0.0"
|
||||
|
|
@ -13797,14 +13814,14 @@ source-map-explorer@^2.1.1:
|
|||
open "^7.0.0"
|
||||
source-map "^0.7.3"
|
||||
temp "^0.9.1"
|
||||
yargs "^15.0.2"
|
||||
yargs "^15.1.0"
|
||||
|
||||
source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259"
|
||||
integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==
|
||||
version "0.5.3"
|
||||
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
|
||||
integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==
|
||||
dependencies:
|
||||
atob "^2.1.1"
|
||||
atob "^2.1.2"
|
||||
decode-uri-component "^0.2.0"
|
||||
resolve-url "^0.2.1"
|
||||
source-map-url "^0.4.0"
|
||||
|
|
@ -14092,14 +14109,16 @@ string-width@^4.1.0, string-width@^4.2.0:
|
|||
strip-ansi "^6.0.0"
|
||||
|
||||
"string.prototype.matchall@^4.0.0 || ^3.0.1":
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.1.tgz#f10fdfa8d1fee12e149fddda14f211b6bb3527da"
|
||||
integrity sha512-vIObm+BWuKKJovfh2/PPCAmePTDdubrgCkhQnbP0oAwD7Jj8IyIM57Hu7Ma7oDdg4oVdh5S1Rd8RviBIPZ8Pfg==
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz#48bb510326fb9fdeb6a33ceaa81a6ea04ef7648e"
|
||||
integrity sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg==
|
||||
dependencies:
|
||||
define-properties "^1.1.3"
|
||||
es-abstract "^1.17.0-next.1"
|
||||
es-abstract "^1.17.0"
|
||||
has-symbols "^1.0.1"
|
||||
regexp.prototype.flags "^1.2.0"
|
||||
internal-slot "^1.0.2"
|
||||
regexp.prototype.flags "^1.3.0"
|
||||
side-channel "^1.0.2"
|
||||
|
||||
string.prototype.padend@^3.0.0:
|
||||
version "3.1.0"
|
||||
|
|
@ -14449,9 +14468,9 @@ terser-webpack-plugin@^1.2.4, terser-webpack-plugin@^1.4.1, terser-webpack-plugi
|
|||
worker-farm "^1.7.0"
|
||||
|
||||
terser@^4.1.2, terser@^4.3.9:
|
||||
version "4.4.3"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-4.4.3.tgz#401abc52b88869cf904412503b1eb7da093ae2f0"
|
||||
integrity sha512-0ikKraVtRDKGzHrzkCv5rUNDzqlhmhowOBqC0XqUHFpW+vJ45+20/IFBcebwKfiS2Z9fJin6Eo+F1zLZsxi8RA==
|
||||
version "4.5.1"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-4.5.1.tgz#63b52d6b6ce344aa6fedcd0ee06a695799eb50bd"
|
||||
integrity sha512-lH9zLIbX8PRBEFCTvfHGCy0s9HEKnNso1Dx9swSopF3VUnFLB8DpQ61tHxoofovNC/sG0spajJM3EIIRSTByiQ==
|
||||
dependencies:
|
||||
commander "^2.20.0"
|
||||
source-map "~0.6.1"
|
||||
|
|
@ -14801,9 +14820,9 @@ uglify-js@3.4.x:
|
|||
source-map "~0.6.1"
|
||||
|
||||
uglify-js@^3.1.4:
|
||||
version "3.7.2"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.2.tgz#cb1a601e67536e9ed094a92dd1e333459643d3f9"
|
||||
integrity sha512-uhRwZcANNWVLrxLfNFEdltoPNhECUR3lc+UdJoG9CBpMcSnKyWA94tc3eAujB1GcMY5Uwq8ZMp4qWpxWYDQmaA==
|
||||
version "3.7.3"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.3.tgz#f918fce9182f466d5140f24bb0ff35c2d32dcc6a"
|
||||
integrity sha512-7tINm46/3puUA4hCkKYo4Xdts+JDaVC9ZPRcG8Xw9R4nhO/gZgUM3TENq8IF4Vatk8qCig4MzP/c8G4u2BkVQg==
|
||||
dependencies:
|
||||
commander "~2.20.3"
|
||||
source-map "~0.6.1"
|
||||
|
|
@ -15352,9 +15371,9 @@ webpack@4.41.2:
|
|||
webpack-sources "^1.4.1"
|
||||
|
||||
webpack@^4.33.0, webpack@^4.38.0:
|
||||
version "4.41.4"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.4.tgz#4bec4125224bdf50efa8be6226c19047599cd034"
|
||||
integrity sha512-Lc+2uB6NjpCWsHI3trkoISOI64h9QYIXenbEWj3bn3oyjfB1lEBXjWAfAyY2sM0rZn41oD5V91OLwKRwS6Wp8Q==
|
||||
version "4.41.5"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.5.tgz#3210f1886bce5310e62bb97204d18c263341b77c"
|
||||
integrity sha512-wp0Co4vpyumnp3KlkmpM5LWuzvZYayDwM2n17EHFr4qxBBbRokC7DJawPJC7TfSFZ9HZ6GsdH40EBj4UV0nmpw==
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.8.5"
|
||||
"@webassemblyjs/helper-module-context" "1.8.5"
|
||||
|
|
@ -15820,10 +15839,10 @@ yargs@^13.3.0:
|
|||
y18n "^4.0.0"
|
||||
yargs-parser "^13.1.1"
|
||||
|
||||
yargs@^15.0.2:
|
||||
version "15.0.2"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.0.2.tgz#4248bf218ef050385c4f7e14ebdf425653d13bd3"
|
||||
integrity sha512-GH/X/hYt+x5hOat4LMnCqMd8r5Cv78heOMIJn1hr7QPPBqfeC6p89Y78+WB9yGDvfpCvgasfmWLzNzEioOUD9Q==
|
||||
yargs@^15.1.0:
|
||||
version "15.1.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.1.0.tgz#e111381f5830e863a89550bd4b136bb6a5f37219"
|
||||
integrity sha512-T39FNN1b6hCW4SOIk1XyTOWxtXdcen0t+XYrysQmChzSipvhBO8Bj0nK1ozAasdk24dNWuMZvr4k24nz+8HHLg==
|
||||
dependencies:
|
||||
cliui "^6.0.0"
|
||||
decamelize "^1.2.0"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user