mirror of https://github.com/ctk-hq/ctk
commit
35cac7e816
@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.0.4 on 2022-08-04 06:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('api', '0002_project_uuid'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='project',
|
||||
name='visibility',
|
||||
field=models.SmallIntegerField(default='1'),
|
||||
),
|
||||
]
|
||||
@ -0,0 +1,47 @@
|
||||
import * as yup from "yup";
|
||||
|
||||
export interface IImportForm {
|
||||
url: string;
|
||||
visibility: string[];
|
||||
}
|
||||
|
||||
export interface IImportFinalValues {
|
||||
url: string;
|
||||
visibility: number;
|
||||
}
|
||||
|
||||
const initialValues: IImportForm = {
|
||||
url: "",
|
||||
visibility: []
|
||||
};
|
||||
|
||||
export const validationSchema = yup.object({
|
||||
url: yup
|
||||
.string()
|
||||
.max(256, "url should be 500 characters or less")
|
||||
.required("url is required")
|
||||
});
|
||||
|
||||
export const getInitialValues = (values?: any): IImportForm => {
|
||||
if (!values) {
|
||||
return {
|
||||
...initialValues
|
||||
};
|
||||
}
|
||||
|
||||
const { url, visibility } = values;
|
||||
|
||||
return {
|
||||
url: url ?? (initialValues.url as string),
|
||||
visibility: visibility ?? []
|
||||
};
|
||||
};
|
||||
|
||||
export const getFinalValues = (values: IImportForm): IImportFinalValues => {
|
||||
const { url, visibility } = values;
|
||||
|
||||
return {
|
||||
url: url ?? "",
|
||||
visibility: visibility.length ? 1 : 0
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,115 @@
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import { Field, Formik } from "formik";
|
||||
import { styled } from "@mui/joy";
|
||||
import { XIcon } from "@heroicons/react/outline";
|
||||
import { CallbackFunction } from "../../../types";
|
||||
import { IImportForm } from "./form-utils";
|
||||
import {
|
||||
getFinalValues,
|
||||
getInitialValues,
|
||||
validationSchema
|
||||
} from "./form-utils";
|
||||
import TextField from "../../global/FormElements/TextField";
|
||||
import { toaster } from "../../../utils";
|
||||
import { reportErrorsAndSubmit } from "../../../utils/forms";
|
||||
import { ScrollView } from "../../ScrollView";
|
||||
import lodash from "lodash";
|
||||
|
||||
interface IModalImportProps {
|
||||
onHide: CallbackFunction;
|
||||
onImport: CallbackFunction;
|
||||
importing: boolean;
|
||||
}
|
||||
|
||||
const FormContainer = styled("div")`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
`;
|
||||
|
||||
const ModalImport = (props: IModalImportProps) => {
|
||||
const { onHide, onImport, importing } = props;
|
||||
|
||||
const handleCreate = useCallback(
|
||||
(values: IImportForm, formik: any) => {
|
||||
const result = getFinalValues(values);
|
||||
onImport(result);
|
||||
toaster(`Importing...`, "success");
|
||||
},
|
||||
[onImport, onHide]
|
||||
);
|
||||
|
||||
const initialValues = useMemo(() => getInitialValues(), []);
|
||||
|
||||
return (
|
||||
<div className="fixed z-50 inset-0 overflow-y-auto">
|
||||
<div className="justify-center items-center flex overflow-x-hidden overflow-y-auto fixed inset-0 outline-none focus:outline-none">
|
||||
<div
|
||||
onClick={onHide}
|
||||
className="opacity-25 fixed inset-0 z-40 bg-black"
|
||||
></div>
|
||||
<div className="relative w-auto my-6 mx-auto max-w-5xl z-50">
|
||||
<div className="border-0 rounded-lg shadow-lg relative flex flex-col w-full bg-white outline-none focus:outline-none">
|
||||
<div className="flex items-center justify-between px-4 py-3 border-b border-solid border-blueGray-200 rounded-t">
|
||||
<h3 className="text-sm font-semibold">Import</h3>
|
||||
<button
|
||||
className="p-1 ml-auto text-black float-right outline-none focus:outline-none"
|
||||
onClick={onHide}
|
||||
>
|
||||
<span className="block outline-none focus:outline-none">
|
||||
<XIcon className="w-4" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
enableReinitialize={true}
|
||||
onSubmit={handleCreate}
|
||||
validationSchema={validationSchema}
|
||||
>
|
||||
{(formik) => (
|
||||
<FormContainer>
|
||||
<div>
|
||||
<ScrollView
|
||||
className="relative px-4 py-3 flex-auto"
|
||||
height={""}
|
||||
>
|
||||
<TextField label="yaml url" name="url" required={true} />
|
||||
|
||||
<label htmlFor="visibility" className="lbl-util">
|
||||
Visibility
|
||||
</label>
|
||||
|
||||
<input
|
||||
id="visibility"
|
||||
name="visibility"
|
||||
className="checkbox-util"
|
||||
type="checkbox"
|
||||
onChange={formik.handleChange}
|
||||
/>
|
||||
|
||||
{importing && <>importing</>}
|
||||
</ScrollView>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-end px-4 py-3 border-t border-solid border-blueGray-200 rounded-b">
|
||||
<button
|
||||
className="btn-util"
|
||||
type="button"
|
||||
onClick={reportErrorsAndSubmit(formik)}
|
||||
>
|
||||
Import
|
||||
</button>
|
||||
</div>
|
||||
</FormContainer>
|
||||
)}
|
||||
</Formik>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModalImport;
|
||||
@ -0,0 +1,38 @@
|
||||
import { EyeIcon, EyeOffIcon } from "@heroicons/react/solid";
|
||||
import { CallbackFunction } from "../../../types";
|
||||
|
||||
interface IVisibilitySwitchProps {
|
||||
onToggle: CallbackFunction;
|
||||
isVisible: boolean;
|
||||
}
|
||||
|
||||
const VisibilitySwitch = (props: IVisibilitySwitchProps) => {
|
||||
const { isVisible, onToggle } = props;
|
||||
|
||||
return (
|
||||
<div className="flex flex items-center justify-end">
|
||||
<button
|
||||
onClick={onToggle}
|
||||
id="theme-toggle"
|
||||
type="button"
|
||||
className="
|
||||
btn-util
|
||||
bg-white
|
||||
focus:ring-0
|
||||
text-gray-500
|
||||
hover:bg-white
|
||||
hover:text-gray-800
|
||||
focus:outline-none
|
||||
text-sm"
|
||||
>
|
||||
{isVisible ? (
|
||||
<EyeIcon id="theme-toggle-light-icon" className="w-5 h-5" />
|
||||
) : (
|
||||
<EyeOffIcon id="theme-toggle-dark-icon" className="w-5 h-5" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default VisibilitySwitch;
|
||||
@ -0,0 +1,18 @@
|
||||
import axios from "axios";
|
||||
import { IImportFinalValues } from "../components/Modal/import/form-utils";
|
||||
import { API_SERVER_URL } from "../constants";
|
||||
import { getLocalStorageJWTKeys } from "../utils";
|
||||
|
||||
export const importProject = async (values: IImportFinalValues) => {
|
||||
const jwtKeys = getLocalStorageJWTKeys();
|
||||
const response = await axios({
|
||||
method: "post",
|
||||
url: `${API_SERVER_URL}/projects/import/`,
|
||||
data: { ...values },
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${jwtKeys.access_token}`
|
||||
}
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
Loading…
Reference in New Issue