+
+
@@ -21,9 +25,15 @@ submissionFormStore.initialize(route.params.route as string);
-
+
Built on
-
Forms Pro
+
+
+
diff --git a/frontend/src/router.ts b/frontend/src/router.ts
index bf404c8..b932d1e 100644
--- a/frontend/src/router.ts
+++ b/frontend/src/router.ts
@@ -1,8 +1,9 @@
import { userResource } from "@/data/user";
-import { createRouter, createWebHistory } from "vue-router";
+import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
import { session } from "./data/session";
+import { isLoginRequired } from "@/utils/form";
-const routes = [
+const routes: RouteRecordRaw[] = [
{
path: "/",
name: "Dashboard",
@@ -27,9 +28,19 @@ const routes = [
component: () => import("@/pages/EditForm.vue"),
},
{
- path: "/p/:route",
+ path: "/p/:route(.*)",
name: "Form Submission Page",
component: () => import("@/pages/SubmissionPage.vue"),
+ meta: { allowGuest: true },
+ beforeEnter: async (to, from) => {
+ const loginRequired = await isLoginRequired(to.params.route as string);
+
+ if (loginRequired && !session.isLoggedIn) {
+ window.location.href = `/login?redirect-to=/forms${to.fullPath}`;
+ return false;
+ }
+ return true;
+ },
},
];
@@ -48,7 +59,11 @@ router.beforeEach(async (to, from, next) => {
if (to.name === "Login" && isLoggedIn) {
next({ name: "Home" });
- } else if (to.name !== "Login" && !isLoggedIn) {
+ } else if (
+ to.name !== "Login" &&
+ !isLoggedIn &&
+ to.meta.allowGuest !== true
+ ) {
window.location.href = `/login?redirect-to=/forms${to.fullPath}`;
} else {
next();
diff --git a/frontend/src/stores/editForm.ts b/frontend/src/stores/editForm.ts
index da16fd7..7f9aac4 100644
--- a/frontend/src/stores/editForm.ts
+++ b/frontend/src/stores/editForm.ts
@@ -98,25 +98,16 @@ export const useEditForm = defineStore("editForm", () => {
}
});
- return formResource.value.setValue.submit(
- {
- title: formResource.value.doc.title,
- fields: formResource.value.doc.fields,
- description: formResource.value.doc.description,
- route: formResource.value.doc.route,
- allow_incomplete: formResource.value.doc.allow_incomplete,
+ return formResource.value.setValue.submit(formResource.value.doc, {
+ onSuccess: () => {
+ toast.success("Form Updated Successfully");
},
- {
- onSuccess: () => {
- toast.success("Form Updated Successfully");
- },
- onError: (error: any) => {
- toast.error("Failed to Update Form", {
- description: error.message,
- });
- },
- }
- );
+ onError: (error: any) => {
+ toast.error("Failed to Update Form", {
+ description: error.message,
+ });
+ },
+ });
}
toast.error("No form resource available");
return Promise.reject(new Error("No form resource available"));
diff --git a/frontend/src/types/form.ts b/frontend/src/types/form.ts
index 5ab0391..c456db2 100644
--- a/frontend/src/types/form.ts
+++ b/frontend/src/types/form.ts
@@ -1,9 +1,14 @@
import { FormField } from "./formfield";
-export interface Form {
+export type Form = {
name: string;
title: string;
description?: string;
fields?: FormField[];
- [key: string]: any;
-}
+ route?: string;
+ is_published?: boolean;
+ allow_incomplete?: boolean;
+ linked_doctype?: string;
+ linked_team_id?: string;
+ login_required?: boolean;
+};
diff --git a/frontend/src/utils/form.ts b/frontend/src/utils/form.ts
new file mode 100644
index 0000000..b5f566c
--- /dev/null
+++ b/frontend/src/utils/form.ts
@@ -0,0 +1,20 @@
+import { useCall } from "frappe-ui";
+
+/**
+ * Check if login is required for a form submission page.
+ *
+ * @param route - The route of the form to check.
+ *
+ * @returns bool - True if login is required, False otherwise.
+ */
+export async function isLoginRequired(route: string) {
+ const loginRequired = useCall({
+ baseUrl: "/api/v2/method/",
+ url: "forms_pro.api.form.is_login_required",
+ params: { route },
+ immediate: false,
+ });
+
+ await loginRequired.execute();
+ return loginRequired.data;
+}
diff --git a/frontend/src/utils/form_fields.ts b/frontend/src/utils/form_fields.ts
index 1cd9b85..7e1487a 100644
--- a/frontend/src/utils/form_fields.ts
+++ b/frontend/src/utils/form_fields.ts
@@ -13,24 +13,34 @@ import {
TimePicker,
Password,
} from "frappe-ui";
+import { Component } from "vue";
+
+export type FormFieldType = {
+ component: Component;
+ props: Record
;
+};
+
+export type FormFields = FormFieldType & {
+ name: string;
+};
// Individual form field components as dictionaries
-export const DataField = {
+export const DataField: FormFieldType = {
component: FormControl,
props: { type: "text", variant: "outline" },
};
-export const NumberField = {
+export const NumberField: FormFieldType = {
component: FormControl,
props: { type: "number", variant: "outline" },
};
-export const EmailField = {
+export const EmailField: FormFieldType = {
component: FormControl,
props: { type: "email", variant: "outline" },
};
-export const DateField = {
+export const DateField: FormFieldType = {
component: DatePicker,
props: {
variant: "outline",
@@ -39,7 +49,7 @@ export const DateField = {
},
};
-export const DateTimeField = {
+export const DateTimeField: FormFieldType = {
component: DateTimePicker,
props: {
format: "DD MMM YYYY, hh:mm A",
@@ -48,7 +58,7 @@ export const DateTimeField = {
},
};
-export const DateRangeField = {
+export const DateRangeField: FormFieldType = {
component: DateRangePicker,
props: {
clearable: true,
@@ -57,7 +67,7 @@ export const DateRangeField = {
},
};
-export const TimeField = {
+export const TimeField: FormFieldType = {
component: TimePicker,
props: {
variant: "outline",
@@ -66,38 +76,38 @@ export const TimeField = {
},
};
-export const PasswordField = {
+export const PasswordField: FormFieldType = {
component: Password,
props: {
variant: "outline",
},
};
-export const RatingField = {
+export const RatingField: FormFieldType = {
component: Rating,
props: {},
};
-export const SelectField = {
+export const SelectField: FormFieldType = {
component: Select,
props: {
variant: "outline",
},
};
-export const SwitchField = {
+export const SwitchField: FormFieldType = {
component: Switch,
props: {},
};
-export const TextareaField = {
+export const TextareaField: FormFieldType = {
component: Textarea,
props: {
variant: "outline",
},
};
-export const TextEditorField = {
+export const TextEditorField: FormFieldType = {
component: TextEditor,
props: {
editorClass:
@@ -112,12 +122,12 @@ export const TextEditorField = {
},
};
-export const CheckboxField = {
+export const CheckboxField: FormFieldType = {
component: Checkbox,
props: {},
};
-export const formFields = [
+export const formFields: FormFields[] = [
{ name: "Data", ...DataField },
{ name: "Number", ...NumberField },
{ name: "Email", ...EmailField },