diff --git a/.vscode/settings.json b/.vscode/settings.json
index e89a70f..b7ada13 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,8 +1,9 @@
{
"cSpell.words": [
- "Formik",
"clsx",
"fontsource",
+ "Formik",
+ "noconflict",
"notistack",
"unmount",
"vditor"
diff --git a/package-lock.json b/package-lock.json
index a90a829..c687e6e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -29,6 +29,7 @@
"@types/node": "^12.20.10",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.3",
+ "ace-builds": "^1.4.13",
"apollo-link-scalars": "^2.1.3",
"configuration": "file:../configuration",
"date-fns": "^2.21.1",
@@ -42,6 +43,7 @@
"notistack": "^1.0.6",
"ramda": "^0.27.1",
"react": "^17.0.2",
+ "react-ace": "^9.4.4",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3",
"typescript": "^4.2.4",
@@ -6711,6 +6713,12 @@
"node": ">= 0.6"
}
},
+ "node_modules/ace-builds": {
+ "version": "1.4.13",
+ "resolved": "https://npm.ivanli.cc/ace-builds/-/ace-builds-1.4.13.tgz",
+ "integrity": "sha512-SOLzdaQkY6ecPKYRDDg+MY1WoGgXA34cIvYJNNoBMGGUswHmlauU2Hy0UL96vW0Fs/LgFbMUjD+6vqzWTldIYQ==",
+ "license": "BSD-3-Clause"
+ },
"node_modules/acorn": {
"version": "7.4.1",
"resolved": "https://npm.ivanli.cc/acorn/-/acorn-7.4.1.tgz",
@@ -18170,7 +18178,6 @@
"version": "4.4.2",
"resolved": "https://npm.ivanli.cc/lodash.get/-/lodash.get-4.4.2.tgz",
"integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=",
- "dev": true,
"license": "MIT"
},
"node_modules/lodash.has": {
@@ -18193,6 +18200,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/lodash.isequal": {
+ "version": "4.5.0",
+ "resolved": "https://npm.ivanli.cc/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+ "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=",
+ "license": "MIT"
+ },
"node_modules/lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://npm.ivanli.cc/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
@@ -22177,6 +22190,23 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-ace": {
+ "version": "9.4.4",
+ "resolved": "https://npm.ivanli.cc/react-ace/-/react-ace-9.4.4.tgz",
+ "integrity": "sha512-gHSH4Wm+jE28pcr4hXKeSwG2DHPZhVlfAfR+VI/dgStnUFWJMPClpRI8emLEYEK/g4cZ4cHY80HTfFwfc4020w==",
+ "license": "MIT",
+ "dependencies": {
+ "ace-builds": "^1.4.12",
+ "diff-match-patch": "^1.0.5",
+ "lodash.get": "^4.4.2",
+ "lodash.isequal": "^4.5.0",
+ "prop-types": "^15.7.2"
+ },
+ "peerDependencies": {
+ "react": "^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0",
+ "react-dom": "^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0"
+ }
+ },
"node_modules/react-app-polyfill": {
"version": "2.0.0",
"resolved": "https://npm.ivanli.cc/react-app-polyfill/-/react-app-polyfill-2.0.0.tgz",
@@ -33853,6 +33883,11 @@
"negotiator": "0.6.2"
}
},
+ "ace-builds": {
+ "version": "1.4.13",
+ "resolved": "https://npm.ivanli.cc/ace-builds/-/ace-builds-1.4.13.tgz",
+ "integrity": "sha512-SOLzdaQkY6ecPKYRDDg+MY1WoGgXA34cIvYJNNoBMGGUswHmlauU2Hy0UL96vW0Fs/LgFbMUjD+6vqzWTldIYQ=="
+ },
"acorn": {
"version": "7.4.1",
"resolved": "https://npm.ivanli.cc/acorn/-/acorn-7.4.1.tgz",
@@ -42172,8 +42207,7 @@
"lodash.get": {
"version": "4.4.2",
"resolved": "https://npm.ivanli.cc/lodash.get/-/lodash.get-4.4.2.tgz",
- "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=",
- "dev": true
+ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
},
"lodash.has": {
"version": "4.5.2",
@@ -42192,6 +42226,11 @@
"integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=",
"dev": true
},
+ "lodash.isequal": {
+ "version": "4.5.0",
+ "resolved": "https://npm.ivanli.cc/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+ "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
+ },
"lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://npm.ivanli.cc/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
@@ -45078,6 +45117,18 @@
"object-assign": "^4.1.1"
}
},
+ "react-ace": {
+ "version": "9.4.4",
+ "resolved": "https://npm.ivanli.cc/react-ace/-/react-ace-9.4.4.tgz",
+ "integrity": "sha512-gHSH4Wm+jE28pcr4hXKeSwG2DHPZhVlfAfR+VI/dgStnUFWJMPClpRI8emLEYEK/g4cZ4cHY80HTfFwfc4020w==",
+ "requires": {
+ "ace-builds": "^1.4.12",
+ "diff-match-patch": "^1.0.5",
+ "lodash.get": "^4.4.2",
+ "lodash.isequal": "^4.5.0",
+ "prop-types": "^15.7.2"
+ }
+ },
"react-app-polyfill": {
"version": "2.0.0",
"resolved": "https://npm.ivanli.cc/react-app-polyfill/-/react-app-polyfill-2.0.0.tgz",
diff --git a/package.json b/package.json
index 9dc96ed..92e8bc6 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
"@types/node": "^12.20.10",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.3",
+ "ace-builds": "^1.4.13",
"apollo-link-scalars": "^2.1.3",
"configuration": "file:../configuration",
"date-fns": "^2.21.1",
@@ -37,6 +38,7 @@
"notistack": "^1.0.6",
"ramda": "^0.27.1",
"react": "^17.0.2",
+ "react-ace": "^9.4.4",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3",
"typescript": "^4.2.4",
diff --git a/src/App.tsx b/src/App.tsx
index 165b373..cc60781 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -6,6 +6,9 @@ function App() {
const { response } = useResponse();
const { body: Body } = response;
+ if (!Body) {
+ return Client has some wrong!;
+ }
return (
diff --git a/src/commons/form/yaml-editor/yaml-editor.tsx b/src/commons/form/yaml-editor/yaml-editor.tsx
new file mode 100644
index 0000000..4d8d04b
--- /dev/null
+++ b/src/commons/form/yaml-editor/yaml-editor.tsx
@@ -0,0 +1,28 @@
+import { FC } from "@curi/react-universal/node_modules/@types/react";
+import { FieldConfig, useField } from "formik";
+import AceEditor from "react-ace";
+import "ace-builds/src-noconflict/mode-yaml";
+import "ace-builds/src-noconflict/theme-github";
+import { styled } from "@mui/system";
+
+const Editor: FC & { label?: string; className?: string }> =
+ ({ label, className, ...props }) => {
+ const [field, , helper] = useField(props);
+ return (
+ helper.setValue(value)}
+ {...props}
+ mode="yaml"
+ theme="github"
+ editorProps={{ $blockScrolling: true }}
+ />
+ );
+ };
+
+export const YamlEditor = Editor;
+styled(Editor)(({ theme }) => ({
+ marginBottom: theme.spacing(2),
+}));
diff --git a/src/generated/graphql.schema.json b/src/generated/graphql.schema.json
index 13deebf..3a3ea36 100644
--- a/src/generated/graphql.schema.json
+++ b/src/generated/graphql.schema.json
@@ -167,6 +167,178 @@
"enumValues": null,
"possibleTypes": null
},
+ {
+ "kind": "OBJECT",
+ "name": "Configuration",
+ "description": null,
+ "fields": [
+ {
+ "name": "id",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pipeline",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "Pipeline",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pipelineId",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "project",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "Project",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "projectId",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "content",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "language",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "ConfigurationLanguage",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "SCALAR",
+ "name": "ID",
+ "description": "The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `\"4\"`) or integer (such as `4`) input value will be accepted as an ID.",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "ENUM",
+ "name": "ConfigurationLanguage",
+ "description": null,
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "JavaScript",
+ "description": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "YAML",
+ "description": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
{
"kind": "INPUT_OBJECT",
"name": "CreatePipelineInput",
@@ -844,6 +1016,39 @@
},
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "setConfiguration",
+ "description": null,
+ "args": [
+ {
+ "name": "setConfigurationInput",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "SetConfigurationInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "Configuration",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": null,
@@ -978,16 +1183,6 @@
"enumValues": null,
"possibleTypes": null
},
- {
- "kind": "SCALAR",
- "name": "ID",
- "description": "The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `\"4\"`) or integer (such as `4`) input value will be accepted as an ID.",
- "fields": null,
- "inputFields": null,
- "interfaces": null,
- "enumValues": null,
- "possibleTypes": null
- },
{
"kind": "OBJECT",
"name": "PipelineTask",
@@ -1783,6 +1978,59 @@
},
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "getConfiguration",
+ "description": null,
+ "args": [
+ {
+ "name": "pipelineId",
+ "description": null,
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "projectId",
+ "description": null,
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": null,
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "Configuration",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": null,
@@ -1790,6 +2038,81 @@
"enumValues": null,
"possibleTypes": null
},
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "SetConfigurationInput",
+ "description": null,
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "pipelineId",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "projectId",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "content",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "language",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "ConfigurationLanguage",
+ "ofType": null
+ }
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
{
"kind": "OBJECT",
"name": "Subscription",
diff --git a/src/generated/graphql.tsx b/src/generated/graphql.tsx
index 736d229..589e84d 100644
--- a/src/generated/graphql.tsx
+++ b/src/generated/graphql.tsx
@@ -26,6 +26,23 @@ export type Commit = {
tasks: Array;
};
+export type Configuration = {
+ __typename?: 'Configuration';
+ id: Scalars['ID'];
+ pipeline: Pipeline;
+ pipelineId: Scalars['String'];
+ project: Project;
+ projectId: Scalars['String'];
+ content: Scalars['String'];
+ name: Scalars['String'];
+ language: ConfigurationLanguage;
+};
+
+export enum ConfigurationLanguage {
+ JavaScript = 'JavaScript',
+ Yaml = 'YAML'
+}
+
export type CreatePipelineInput = {
projectId: Scalars['String'];
branch: Scalars['String'];
@@ -75,6 +92,7 @@ export type Mutation = {
deletePipeline: Scalars['Float'];
createPipelineTask: PipelineTask;
stopPipelineTask: Scalars['Boolean'];
+ setConfiguration: Configuration;
};
@@ -117,6 +135,11 @@ export type MutationStopPipelineTaskArgs = {
id: Scalars['String'];
};
+
+export type MutationSetConfigurationArgs = {
+ setConfigurationInput: SetConfigurationInput;
+};
+
export type Pipeline = {
__typename?: 'Pipeline';
id: Scalars['ID'];
@@ -191,6 +214,7 @@ export type Query = {
commits?: Maybe>;
listPipelineTaskByPipelineId: Array;
pipelineTask: PipelineTask;
+ getConfiguration: Configuration;
};
@@ -223,6 +247,20 @@ export type QueryPipelineTaskArgs = {
id: Scalars['String'];
};
+
+export type QueryGetConfigurationArgs = {
+ pipelineId?: Maybe;
+ projectId?: Maybe;
+ id?: Maybe;
+};
+
+export type SetConfigurationInput = {
+ pipelineId: Scalars['String'];
+ projectId: Scalars['String'];
+ content: Scalars['String'];
+ language: ConfigurationLanguage;
+};
+
export type Subscription = {
__typename?: 'Subscription';
syncCommits?: Maybe;
diff --git a/src/pipelines/index.ts b/src/pipelines/index.ts
index 91c55d3..6199c89 100644
--- a/src/pipelines/index.ts
+++ b/src/pipelines/index.ts
@@ -1,3 +1,4 @@
export * from './pipeline-detail';
export * from './pipeline-list';
export * from './queries';
+export * from "./runtime-config-editor";
diff --git a/src/pipelines/mutations.ts b/src/pipelines/mutations.ts
index bc3795b..d012b8c 100644
--- a/src/pipelines/mutations.ts
+++ b/src/pipelines/mutations.ts
@@ -41,3 +41,12 @@ export const DELETE_PIPELINE = gql`
deletePipeline(id: $id)
}
`;
+
+
+export const SET_CONFIGURATION = gql`
+ mutation SetConfiguration($configuration: SetConfigurationInput!) {
+ setConfiguration(setConfigurationInput: $configuration) {
+ id
+ }
+ }
+`;
\ No newline at end of file
diff --git a/src/pipelines/pipeline-list.tsx b/src/pipelines/pipeline-list.tsx
index a2a983a..7d34d17 100644
--- a/src/pipelines/pipeline-list.tsx
+++ b/src/pipelines/pipeline-list.tsx
@@ -5,17 +5,13 @@ import {
ListItem,
Typography,
ListItemText,
- ListItemSecondaryAction,
- IconButton,
Menu,
MenuItem,
PopoverPosition,
- styled,
} from "@mui/material";
-import { FC, MouseEventHandler, useMemo, useState, MouseEvent } from "react";
+import { FC, useMemo, useState, MouseEvent } from "react";
import { Pipeline, Project } from "../generated/graphql";
-import { CallMerge, Edit } from "@mui/icons-material";
-import { any, values } from "ramda";
+import { CallMerge } from "@mui/icons-material";
import { Divider } from "@material-ui/core";
interface Props {
@@ -79,6 +75,17 @@ export const PipelineList: FC = ({ projectId }) => {
}),
});
};
+ const modifyRuntimeConfiguration = () => {
+ navigate({
+ url: url({
+ name: "edit-runtime-configuration",
+ params: {
+ pipelineId: contextMenu![1].id,
+ projectId: contextMenu![1].project.id,
+ },
+ }),
+ });
+ };
return (
<>
@@ -102,7 +109,14 @@ export const PipelineList: FC = ({ projectId }) => {
anchorReference="anchorPosition"
anchorPosition={contextMenu?.[0]}
>
-
+