[CORL-159, CORL-160] Stream Config Tab (#2219)

* feat: Implement stream configuration tab

* feat: split profile & configure into separate bundles

* chore: better role logic

* fix+chore: add test cases, implement expectAndFail, refactor tests

* chore: add some comments

* chore: Update src/core/client/framework/lib/form/helpers.tsx

Co-Authored-By: cvle <vinh@wikiwi.io>

* feat: support new graphql mutations/schema

* fix: ci fixes

* fix: improvement to revision loading

* fix: updated some tests

* fix: adapt client to changes

* fix: remove obsolote isClosed in UpdateStory

* ci: increase no_output_timeout for build
This commit is contained in:
Kiwi
2019-03-18 22:07:52 +01:00
committed by GitHub
parent c738d9a355
commit 9eb5afbb2b
128 changed files with 2249 additions and 1081 deletions
@@ -0,0 +1,8 @@
import { Environment } from "relay-runtime";
export default function getStory(environment: Environment, id: string) {
return environment
.getStore()
.getSource()
.get(id);
}
@@ -0,0 +1,15 @@
import { Environment } from "relay-runtime";
import getStory from "./getStory";
export default function getStorySettings(environment: Environment, id: string) {
const story = getStory(environment, id);
if (!story) {
return null;
}
const storySettingsRef = story.settings.__ref;
return environment
.getStore()
.getSource()
.get(storySettingsRef);
}
@@ -7,3 +7,5 @@ export { default as redirectOAuth2 } from "./redirectOAuth2";
export {
default as getParamsFromHashAndClearIt,
} from "./getParamsFromHashAndClearIt";
export { default as getStory } from "./getStory";
export { default as getStorySettings } from "./getStorySettings";
@@ -0,0 +1,44 @@
import { FormApi } from "final-form";
import { merge } from "lodash";
import React from "react";
interface Props {
form: FormApi;
rootKey?: string;
children: (
params: {
onInitValues: (data: any) => void;
}
) => React.ReactNode;
}
/**
* FormInitializer exposes `onInitValues` property as a render prop.
* This prop can be called multiple times until `FormInitializer` will
* run `form.initizalize` during mount.
*
* This is useful if you're initialization data is spread across components.
*/
class FormInitializer extends React.Component<Props> {
private initialValues: any = {};
public componentDidMount() {
let values = this.initialValues;
if (this.props.rootKey) {
values = { [this.props.rootKey]: values };
}
this.props.form.initialize(values);
}
private handlePartialInit = (values: any) => {
this.initialValues = merge({}, this.initialValues, values);
};
public render() {
return this.props.children({
onInitValues: this.handlePartialInit,
});
}
}
export default FormInitializer;
@@ -0,0 +1,22 @@
import { noop } from "lodash";
import React from "react";
export type SubmitHook = (
data: any,
actions: {
// Callback will be called after all validations has passed and
// the submit has not been cancelled.
onExecute: (cb: () => Promise<any>) => void;
cancel: (errors?: Record<string, React.ReactNode>) => void;
}
) => Promise<any> | any;
export type RemoveSubmitHook = () => void;
export type AddSubmitHook = (hook: SubmitHook) => RemoveSubmitHook;
export type SubmitHookContext = AddSubmitHook;
const { Provider, Consumer } = React.createContext<SubmitHookContext>(
() => noop
);
export const SubmitHookContextProvider = Provider;
export const SubmitHookContextConsumer = Consumer;
@@ -0,0 +1,85 @@
import { FormApi } from "final-form";
import React from "react";
import { InvalidRequestError } from "talk-framework/lib/errors";
import { AddSubmitHook, SubmitHook, SubmitHookContextProvider } from "./";
interface Props {
onExecute: (data: any, form: FormApi) => Promise<void>;
children: (
params: {
onSubmit: (settings: any, form: FormApi) => void;
}
) => React.ReactNode;
}
/**
* SubmitHookContainer provides the SubmitHook Context and will
* run all hooks when calling the `onSubmit` render prop.
* If the submit was not cancelled, `onExecute` will be called in
* the end, e.g. to call the mutation with the final data.
*/
class SubmitHookContainer extends React.Component<Props> {
private submitHooks: SubmitHook[] = [];
private handleSave = async (data: any, form: FormApi) => {
let cancelled = false;
let formErrors: Record<string, React.ReactNode> = {};
const executeCallbacks: Array<() => Promise<any>> = [];
const cancel = (errors: Record<string, React.ReactNode>) => {
cancelled = true;
formErrors = { ...errors, ...formErrors };
};
const onExecute = (cb: () => Promise<any>) => {
executeCallbacks.push(cb);
};
try {
// Call submit hooks, that can manipulate what
// we send as the mutation.
let nextData = data;
for (const hook of this.submitHooks) {
const result = await hook(nextData, { cancel, onExecute });
if (result) {
nextData = result;
}
}
if (cancelled) {
return formErrors;
}
executeCallbacks.push(() => this.props.onExecute(nextData, form));
for (const c of executeCallbacks.map(cb => cb())) {
await c;
}
} catch (error) {
if (error instanceof InvalidRequestError) {
return error.invalidArgs;
}
// tslint:disable-next-line:no-console
console.error(error);
}
return;
};
private addSubmitHook: AddSubmitHook = hook => {
this.submitHooks.push(hook);
return () => {
this.submitHooks = this.submitHooks.filter(h => h !== hook);
};
};
public render() {
return (
<>
<SubmitHookContextProvider value={this.addSubmitHook}>
{this.props.children({
onSubmit: this.handleSave,
})}
</SubmitHookContextProvider>
</>
);
}
}
export default SubmitHookContainer;
@@ -44,6 +44,7 @@ export const formatPercentage = (v: any) => {
return Math.round(v * 100).toString();
};
export const parseBool = (v: any) => Boolean(v);
export const parseStringBool = (v: string) => v === "true";
export const parseNewLineDelimitedString = (v: string) => v.split("\n");
@@ -0,0 +1,5 @@
export * from "./helpers";
export * from "./SubmitHookContext";
export { default as withSubmitHookContext } from "./withSubmitHookContext";
export { default as SubmitHookHandler } from "./SubmitHookHandler";
export { default as FormInitializer } from "./FormInitializer";
@@ -0,0 +1,12 @@
import { createContextHOC } from "talk-framework/helpers";
import {
SubmitHookContext,
SubmitHookContextConsumer,
} from "./SubmitHookContext";
const withSubmitHookContext = createContextHOC<SubmitHookContext>(
"withSubmitHookContext",
SubmitHookContextConsumer
);
export default withSubmitHookContext;
@@ -24,11 +24,7 @@ export async function commitMutationPromiseNormalized<T extends OperationBase>(
environment: Environment,
config: MutationPromiseConfig<T>
): Promise<T["response"][keyof T["response"]]> {
try {
return await commitMutationPromise(environment, config);
} catch (e) {
throw e;
}
return await commitMutationPromise(environment, config);
}
/**
+5 -3
View File
@@ -2,9 +2,11 @@ import { RestClient } from "../lib/rest";
export interface InstallInput {
tenant: {
organizationName: string;
organizationContactEmail: string;
organizationURL: string;
organization: {
name: string;
contactEmail: string;
url: string;
};
domains: string[];
};
user: {