Skip to content

Commit 18ce372

Browse files
committed
feat: iform type
BREAKING CHANGE: modalTheme no longer a valid prop
1 parent cbc4201 commit 18ce372

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1172
-1122
lines changed

packages/common-helpers/src/form/composable.ts

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,35 +40,36 @@ export default function useForm(options: iPluginOptions = {}) {
4040
request: tResponseFn<R, RV>,
4141
inputs: RV | FormInput[] = [],
4242
event?: Event,
43+
silent = false,
4344
plainValues = true
4445
): Promise<iFormResponse<R, HTMLElement | string>> {
4546
const { values, invalidInputs } = getFormValues<RV>(inputs, plainValues);
4647
const modalTarget = (event?.target as HTMLElement)?.closest("dialog") || "body";
48+
const withSwal = !silent && isBrowser;
4749
let errors;
4850
let requestHadErrors = false;
4951
let newResponse: iFetchResponse<R> = {};
5052

5153
if (!invalidInputs.length) {
5254
try {
53-
if (isBrowser) Swal.fireLoader({ target: modalTarget });
55+
if (withSwal) Swal.fireLoader({ target: modalTarget });
5456

5557
newResponse = await request(values);
58+
// request went ok, but still returned errors
59+
errors = newResponse.errors;
5660

57-
if (newResponse?.errors) {
58-
errors = newResponse.errors;
59-
60-
if (errors || !newResponse.data) requestHadErrors = true;
61+
// empty response can be server error
62+
if (newResponse.data === null || newResponse.data === undefined) {
63+
requestHadErrors = true;
6164
}
6265
} catch (err) {
63-
/**
64-
* Network error probably
65-
*/
66+
// Network error probably
67+
6668
errors = err;
67-
requestHadErrors = true;
6869
// eslint-disable-next-line no-console
6970
console.error(err);
7071

71-
if (isBrowser) {
72+
if (withSwal) {
7273
const { value } = await Swal.fire({
7374
title: t("swal.connection_error"),
7475
text: t("swal.connection_error_message"),
@@ -82,8 +83,17 @@ export default function useForm(options: iPluginOptions = {}) {
8283
// Page reload if user wish to
8384
if (value) location.reload();
8485
}
86+
87+
return {
88+
invalidInputs,
89+
withErrors: true,
90+
requestHadErrors: true,
91+
validationHadErrors: false,
92+
errors,
93+
modalTarget,
94+
};
8595
}
86-
} else if (isBrowser) {
96+
} else if (withSwal) {
8797
// invalid input filling
8898
Swal.fire({
8999
title: t("swal.incomplete_data"),
@@ -93,12 +103,12 @@ export default function useForm(options: iPluginOptions = {}) {
93103
});
94104
}
95105

96-
const validationHadErrors = invalidInputs.length > 0 || !!(errors && !requestHadErrors);
97-
const withErrors = requestHadErrors || validationHadErrors;
106+
const validationHadErrors = invalidInputs.length > 0;
107+
const withErrors = !!errors || requestHadErrors || validationHadErrors;
98108
const response = newResponse.data;
99109

100-
// hide loader
101-
if (isBrowser && !validationHadErrors && response) Swal.close();
110+
// success, hide loader
111+
if (withSwal && !validationHadErrors) Swal.close();
102112

103113
return {
104114
response,

packages/common-helpers/src/form/input.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,3 +255,11 @@ export class FormInput<V extends iFormValue = iFormValue>
255255
return _.isEqual(this.getObject(this), this.getObject(other));
256256
}
257257
}
258+
259+
export interface iForm {
260+
title?: string;
261+
inputs: FormInput[];
262+
listen?: boolean;
263+
/** Make all inputs read only by disabling them */
264+
readonly?: boolean;
265+
}

packages/common-helpers/src/form/utils.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,9 @@ export function getFormInputsValues<V extends Record<string, any>>(
222222

223223
/**
224224
* Returns the actual data object to send to the api
225+
* @param inputs The form inputs.
226+
* @param plainValues Whether or not to remove unnecessary arrays.
227+
* @returns An object containing the form values and invalid inputs.
225228
*/
226229
export function getFormValues<V extends Record<string, any>>(
227230
inputs: V | FormInput[],

packages/common-helpers/src/locale/en.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ export const localeBase: tLocaleBase = {
4141
swal: {
4242
cancel: "Cancel",
4343
continue: "Continue",
44-
connection_error: "¡Connection error!",
44+
error: "Error!",
45+
error_message: "Something went wrong!",
46+
connection_error: "Connection error!",
4547
connection_error_message:
4648
"The server is not responding. Please check your network or try again later",
4749
connection_error_confirm: "Retry",

packages/common-helpers/src/locale/es.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ export const localeBase: tLocaleBase = {
4141
swal: {
4242
cancel: "Cancelar",
4343
continue: "Continuar",
44+
error: "¡Error!",
45+
error_message: "¡Sucedio algo malo!",
4446
connection_error: "¡Error de conexion!",
4547
connection_error_message:
4648
"El servidor no responde. Por favor verifica tu conexion o intentalo de nuevo mas tarde",

packages/common-types/src/locale.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,11 @@ export type tLocaleBase = {
5353
cancel: string;
5454
/** @example "Continue" */
5555
continue: string;
56-
/** @example "¡Connection error!" */
56+
/** @example "Error!" */
57+
error: string;
58+
/** @example "Something went wrong!" */
59+
error_message: string;
60+
/** @example "Connection error!" */
5761
connection_error: string;
5862
/** @example "The server is not responding. Please check your network or try again later" */
5963
connection_error_message: string;

packages/components-vue/src/components/Dropdown.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import useModifiers from "../composables/modifiers";
3838
import useTheme from "../composables/theme";
3939
import { useHelpers } from "../composables/utils";
40+
import { eColors } from "@open-xamu-co/ui-common-enums";
4041
4142
type tAlignFirstX = "right" | "left";
4243
type tAlignFirstY = "top" | "bottom";
@@ -67,7 +68,9 @@
6768
6869
defineOptions({ name: "DropdownSimple", inheritAttrs: false });
6970
70-
const props = defineProps<iDropdownProps>();
71+
const props = withDefaults(defineProps<iDropdownProps>(), {
72+
theme: eColors.SECONDARY,
73+
});
7174
const emit = defineEmits(["close", "update:model-value"]);
7275
7376
const { getModifierClasses: GMC } = useHelpers(useUtils);

packages/components-vue/src/components/Modal.vue

Lines changed: 14 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,12 @@
108108
ref,
109109
watch,
110110
Teleport,
111-
type RendererElement,
111+
getCurrentInstance,
112112
} from "vue";
113113
import _ from "lodash";
114114
115115
import { useI18n, useSwal } from "@open-xamu-co/ui-common-helpers";
116+
import { eColors } from "@open-xamu-co/ui-common-enums";
116117
117118
import BaseErrorBoundary from "./base/ErrorBoundary.vue";
118119
import BaseWrapper from "./base/Wrapper.vue";
@@ -122,62 +123,11 @@
122123
import ActionButtonToggle from "./action/ButtonToggle.vue";
123124
import LoaderSimple from "./loader/Simple.vue";
124125
125-
import type { iUseThemeProps } from "../types/props";
126+
import type { iModalButtonConfig, iModalProps } from "../types/props";
126127
import useTheme from "../composables/theme";
127128
import useUUID from "../composables/uuid";
128129
import { useHelpers } from "../composables/utils";
129130
130-
interface iButtonConfig {
131-
title?: string;
132-
visible?: boolean;
133-
btnClass?: string;
134-
}
135-
136-
interface iModalProps extends iUseThemeProps {
137-
/**
138-
* Modal is loading
139-
* Some of the modal contents could be still loading
140-
*/
141-
loading?: boolean;
142-
/**
143-
* The title of the modal shown in .x-modal-header div. If empty title is not rendered
144-
*/
145-
title?: string;
146-
subtitle?: string;
147-
/**
148-
* :class object which is attached to the modal modal element
149-
*/
150-
modalClass?: string | string[] | Record<string, boolean>;
151-
/**
152-
* Save button config
153-
*/
154-
saveButton?: iButtonConfig & { disabled?: boolean };
155-
/**
156-
* Cancel button config
157-
*/
158-
cancelButton?: iButtonConfig;
159-
/**
160-
* Are modal requirement meet?
161-
* This is intended to prevent the usage of certain modals
162-
*
163-
* Ex: user does not have enough permissions
164-
*/
165-
hide?: boolean;
166-
hideMessage?: string;
167-
hideFooter?: boolean;
168-
/**
169-
* disables modal
170-
*/
171-
disabled?: boolean;
172-
// PRIVATE
173-
/**
174-
* Shows/hides the modal
175-
* @private
176-
*/
177-
modelValue?: boolean;
178-
target?: string | RendererElement;
179-
}
180-
181131
/**
182132
* Based on @innologica/vue-stackable-modal
183133
* Modified to support vue3
@@ -188,12 +138,15 @@
188138
189139
defineOptions({ name: "ModalSimple", inheritAttrs: false });
190140
191-
const props = defineProps<iModalProps>();
141+
const props = withDefaults(defineProps<iModalProps>(), {
142+
theme: eColors.SECONDARY,
143+
});
192144
const emit = defineEmits(["save", "close", "update:model-value"]);
193145
194146
const { t } = useHelpers(useI18n);
195147
const Swal = useHelpers(useSwal);
196148
const { themeClasses, invertedThemeValues } = useTheme(props, true);
149+
const router = getCurrentInstance()?.appContext.config.globalProperties.$router;
197150
const { uuid } = useUUID();
198151
199152
const resolver = ref<(r?: boolean) => void>();
@@ -208,13 +161,13 @@
208161
209162
return `modal_${seed.replaceAll(" ", "") || randomId}`;
210163
});
211-
const saveButtonOptions = computed<iButtonConfig & { disabled?: boolean }>(() => ({
164+
const saveButtonOptions = computed<iModalButtonConfig & { disabled?: boolean }>(() => ({
212165
title: t("ok"),
213166
visible: !!props.saveButton?.title,
214167
btnClass: "",
215168
...(!!props.saveButton && props.saveButton),
216169
}));
217-
const cancelButtonOptions = computed<iButtonConfig>(() => ({
170+
const cancelButtonOptions = computed<iModalButtonConfig>(() => ({
218171
title: t("close"),
219172
visible: true,
220173
btnClass: "",
@@ -283,6 +236,11 @@
283236
},
284237
{ immediate: true }
285238
);
239+
240+
if (!router?.currentRoute) return;
241+
242+
// close on route change
243+
watch(router.currentRoute, () => closeModal(), { immediate: false });
286244
});
287245
onUnmounted(closeModal);
288246
</script>

0 commit comments

Comments
 (0)