Skip to content

Commit

Permalink
Merge pull request #18 from deepsquare-io/chore/release-v.1.1.0
Browse files Browse the repository at this point in the history
Chore/release v.1.1.0
  • Loading branch information
Lymnah authored Aug 16, 2023
2 parents 6f2cd30 + 6a5bf4a commit c245510
Show file tree
Hide file tree
Showing 12 changed files with 199 additions and 11 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@deepsquare/app.deepsquare.io",
"version": "1.0.1",
"version": "1.1.0",
"description": "Full-stack application of the DeepSquare Investment project base on Next.js.",
"keywords": [
"deepsquare",
Expand Down Expand Up @@ -90,6 +90,7 @@
"tailwindcss": "^3.2.7",
"tsyringe": "^4.8.0",
"type-graphql": "2.0.0-beta.2",
"uuid": "^9.0.0",
"vanilla-jsoneditor": "^0.17.8",
"viem": "^0.3.35",
"wagmi": "^1.0.9",
Expand Down Expand Up @@ -118,6 +119,7 @@
"@types/lodash": "^4.14.191",
"@types/prop-types": "^15.7.5",
"@types/react": "^18.2.13",
"@types/uuid": "^9.0.2",
"@typescript-eslint/eslint-plugin": "^5.60.0",
"@typescript-eslint/parser": "^5.60.0",
"@vue/compiler-sfc": "^3.2.47",
Expand Down
10 changes: 10 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

60 changes: 51 additions & 9 deletions src/app/sandbox/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// You should have received a copy of the GNU General Public License along with Nexus. If not, see <https://www.gnu.org/licenses/>.
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import { useSearchParams } from 'next/navigation';
import randomWords from 'random-words';
import type { SubmitHandler } from 'react-hook-form';
import { FormProvider, useForm } from 'react-hook-form';
Expand All @@ -20,6 +21,7 @@ import CreditSubform from '@components/forms/CreditSubform';
import CustomLink from '@components/routing/Link';
import Card from '@components/ui/containers/Card/Card';
import type { Job } from '@graphql/external/sbatchServiceClient/generated/Types';
import { useGetWorkflowQuery } from '@graphql/internal/client/generated/getWorkflow.generated';
import { yupResolver } from '@hookform/resolvers/yup';
import useBalances from '@hooks/useBalances';
import useGetMinimumAmount from '@hooks/useGetMinimumAmount';
Expand All @@ -28,6 +30,7 @@ import { authContext } from '@lib/contexts/AuthContext';
import { isWeb2 } from '@lib/types/AuthMethod';
import type { WorkloadFormData } from '@lib/types/WorkloadFormData';
import WorkloadType from '@lib/types/enums/WorkloadType';
import LoadingButton from '@mui/lab/LoadingButton';
import formatCredit from '@utils/format/formatCredit';
import { formatWei } from '@utils/format/formatWei';

Expand Down Expand Up @@ -57,6 +60,8 @@ const schema = (maxAmount: bigint, minAmount: bigint, ignoreBalance: boolean) =>

type Content = { json: Job } | { text: string };

type Store = { content: Content; initialized: boolean };

function isJson(content: Content): content is { json: Job } {
return (content as { json: Job }).json !== undefined;
}
Expand All @@ -83,25 +88,47 @@ const SandboxPage: NextPage = () => {
const { balance_wCredit } = useBalances();
const { data: minAmount } = useGetMinimumAmount();
const { authMethod } = useContext(authContext);
const searchParams = useSearchParams();
const workflowId = searchParams.get('workflowId');

const [store, setStore] = useState<Store>(() => {
if (typeof window === 'undefined') return { content: { text: JSON.stringify(defaultJob) }, initialized: false };
const storedContent = localStorage.getItem(workflowId ? `sandbox-${workflowId}` : 'sandbox');
return storedContent
? (JSON.parse(storedContent) as Store)
: {
content: { text: JSON.stringify(defaultJob) },
initialized: workflowId === null,
};
});

const [content, setContent] = useState<Content>(() => {
if (typeof window === 'undefined') return { text: JSON.stringify(defaultJob) };
const storedContent = localStorage.getItem('userContent');
return storedContent ? (JSON.parse(storedContent) as Content) : { text: JSON.stringify(defaultJob) };
const { data, loading } = useGetWorkflowQuery({
variables: { workflowId: workflowId! },
skip: !workflowId,
onCompleted: (data) => {
if (data.getWorkflow && !store.initialized) {
setStore({
content: { json: JSON.parse(data.getWorkflow) },
initialized: true,
});
}
},
});

let json: any;

try {
json = isJson(content) ? content.json : JSON.parse(content.text);
json = isJson(store.content) ? store.content.json : JSON.parse(store.content.text);
} catch (e) {
json = defaultJob;
}

const [jsonErrors, setJsonErrors] = useState<ContentErrors>({ validationErrors: [] });

useEffect(() => {
localStorage.setItem('userContent', JSON.stringify(content));
}, [content]);
if (!store.initialized) return;
localStorage.setItem(workflowId ? `sandbox-${workflowId}` : 'sandbox', JSON.stringify(store));
}, [store, workflowId]);

const methods = useForm<CreditSubformData & WorkloadFormData>({
defaultValues: {
Expand Down Expand Up @@ -149,20 +176,35 @@ const SandboxPage: NextPage = () => {
<Card className="flex flex-col grow p-8" title="Write your workflow file">
<div className="pt-5">
<MemoJsonEditor
content={content}
content={store.content}
onChange={(
newContent: Content,
previousContent: Content,
{ contentErrors }: { contentErrors: ContentErrors },
) => {
setJsonErrors(contentErrors);
setContent(newContent);
setStore((prev) => {
return { content: newContent, initialized: prev.initialized };
});
}}
/>
<LoadingButton
className="mt-5"
loading={loading}
onClick={() => {
setStore({
content: { text: data?.getWorkflow ? data?.getWorkflow : JSON.stringify(defaultJob) },
initialized: true,
});
}}
>
Reset
</LoadingButton>
</div>
</Card>

<CreditSubform
defaultDuration={20}
gpuQty={
json?.resources?.tasks && json?.resources?.gpusPerTask
? json.resources.tasks * json.resources.gpusPerTask
Expand Down
1 change: 0 additions & 1 deletion src/components/ui/containers/JsonEditor/JsonEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ function JsonEditor(props: Record<string, any>) {
return () => {
void jsonEditorPromise.then((editor) => {
void editor.destroy();
editorRef.current = null;
});
};
// eslint-disable-next-line react-hooks/exhaustive-deps
Expand Down
10 changes: 10 additions & 0 deletions src/database/Workflow/Workflow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright 2023 Deepsquare Association
// This file is part of Foobar.
// Foobar is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
// Foobar is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with Foobar. If not, see <https://www.gnu.org/licenses/>.

export default interface Workflow {
_id: string;
content: string;
}
18 changes: 18 additions & 0 deletions src/database/Workflow/WorkflowModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2023 Deepsquare Association
// This file is part of Foobar.
// Foobar is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
// Foobar is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with Foobar. If not, see <https://www.gnu.org/licenses/>.
import type { Model } from 'mongoose';
import { model, models, Schema } from 'mongoose';
import { v4 } from 'uuid';
import type Workflow from './Workflow';

export const WorkflowSchema = new Schema<Workflow>({
_id: { type: String, default: v4 },
content: { type: String, required: true },
});

const WorkflowModel: Model<Workflow> = models.Workflow ?? model('Workflow', WorkflowSchema, 'workflows');

export default WorkflowModel;
5 changes: 5 additions & 0 deletions src/graphql/internal/client/generated/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ export type ProviderPrices = {

export type Query = {
getJobHash: GetJobHashOutput;
getWorkflow?: Maybe<Scalars['String']>;
listJobs: Array<FullJobSummary>;
ping: Scalars['String'];
};
Expand All @@ -178,6 +179,10 @@ export type QueryGetJobHashArgs = {
jobId: Scalars['Hex'];
};

export type QueryGetWorkflowArgs = {
workflowId: Scalars['String'];
};

export type QueryListJobsArgs = {
userId: Scalars['String'];
};
Expand Down
49 changes: 49 additions & 0 deletions src/graphql/internal/client/generated/getWorkflow.generated.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
import type * as Types from './Types';

const defaultOptions = {} as const;
export type GetWorkflowQueryVariables = Types.Exact<{
workflowId: Types.Scalars['String'];
}>;

export type GetWorkflowQuery = { getWorkflow?: string | null };

export const GetWorkflowDocument = /*#__PURE__*/ gql`
query GetWorkflow($workflowId: String!) {
getWorkflow(workflowId: $workflowId)
}
`;

/**
* __useGetWorkflowQuery__
*
* To run a query within a React component, call `useGetWorkflowQuery` and pass it any options that fit your needs.
* When your component renders, `useGetWorkflowQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useGetWorkflowQuery({
* variables: {
* workflowId: // value for 'workflowId'
* },
* });
*/
export function useGetWorkflowQuery(baseOptions: Apollo.QueryHookOptions<GetWorkflowQuery, GetWorkflowQueryVariables>) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<GetWorkflowQuery, GetWorkflowQueryVariables>(GetWorkflowDocument, options);
}
export function useGetWorkflowLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<GetWorkflowQuery, GetWorkflowQueryVariables>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<GetWorkflowQuery, GetWorkflowQueryVariables>(GetWorkflowDocument, options);
}
export type GetWorkflowQueryHookResult = ReturnType<typeof useGetWorkflowQuery>;
export type GetWorkflowLazyQueryHookResult = ReturnType<typeof useGetWorkflowLazyQuery>;
export type GetWorkflowQueryResult = Apollo.QueryResult<GetWorkflowQuery, GetWorkflowQueryVariables>;
export function refetchGetWorkflowQuery(variables: GetWorkflowQueryVariables) {
return { query: GetWorkflowDocument, variables: variables };
}
21 changes: 21 additions & 0 deletions src/graphql/internal/client/generated/introspection.json
Original file line number Diff line number Diff line change
Expand Up @@ -1228,6 +1228,27 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "getWorkflow",
"description": null,
"args": [
{
"name": "workflowId",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"type": { "kind": "SCALAR", "name": "String", "ofType": null },
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "listJobs",
"description": null,
Expand Down
8 changes: 8 additions & 0 deletions src/graphql/internal/client/operations/getWorkflow.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Copyright 2023 Deepsquare Association
# This file is part of Nexus.
# Nexus is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
# Nexus is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along with Nexus. If not, see <https://www.gnu.org/licenses/>.
query GetWorkflow($workflowId: String!) {
getWorkflow(workflowId: $workflowId)
}
2 changes: 2 additions & 0 deletions src/graphql/internal/createSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import CancelJobMutation from '@graphql/internal/mutations/CancelJobMutation';
import CreateUserMutation from '@graphql/internal/mutations/CreateUserMutation';
import RequestJobMutation from '@graphql/internal/mutations/RequestJobMutation';
import GetJobHashQuery from '@graphql/internal/queries/GetJobHashQuery';
import GetWorkflowQuery from '@graphql/internal/queries/GetWorkflowQuery';
import ListJobsQuery from '@graphql/internal/queries/ListJobsQuery';
import PingQuery from '@graphql/internal/queries/PingQuery';
import { BigIntScalar } from '@graphql/internal/scalars/BigIntScalar';
Expand All @@ -34,6 +35,7 @@ export default function createSchema() {
resolvers: [
// Queries
GetJobHashQuery,
GetWorkflowQuery,
ListJobsQuery,
PingQuery,

Expand Down
22 changes: 22 additions & 0 deletions src/graphql/internal/queries/GetWorkflowQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2023 Deepsquare Association
// This file is part of Foobar.
// Foobar is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
// Foobar is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with Foobar. If not, see <https://www.gnu.org/licenses/>.
import { injectable } from 'tsyringe';
import { Arg, Query, Resolver } from 'type-graphql';
import WorkflowModel from '../../../database/Workflow/WorkflowModel';

@injectable()
@Resolver()
export default class GetWorkflowQuery {
@Query(() => String, { nullable: true })
async getWorkflow(@Arg('workflowId', () => String) workflowId: string) {
const workflow = await WorkflowModel.findById(workflowId).lean().exec();
if (!workflow) {
return null;
} else {
return workflow.content;
}
}
}

1 comment on commit c245510

@vercel
Copy link

@vercel vercel bot commented on c245510 Aug 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nexus – ./

nexus-deepsquare.vercel.app
app.deepsquare.run
nexus-git-main-deepsquare.vercel.app

Please sign in to comment.