From e30a5a4c281a2648950cd190db707a979eae5dc1 Mon Sep 17 00:00:00 2001 From: Nicolas Meienberger Date: Mon, 23 May 2022 20:46:26 +0000 Subject: [PATCH 1/3] Add field type url --- apps/prowlarr/docker-compose.yml | 3 +- .../src/components/Form/validators.ts | 67 ++++++++++++++----- packages/dashboard/src/core/types.ts | 1 + 3 files changed, 55 insertions(+), 16 deletions(-) diff --git a/apps/prowlarr/docker-compose.yml b/apps/prowlarr/docker-compose.yml index 4885600e..629babec 100644 --- a/apps/prowlarr/docker-compose.yml +++ b/apps/prowlarr/docker-compose.yml @@ -5,7 +5,8 @@ services: image: ghcr.io/linuxserver/prowlarr:develop environment: - TZ=${TZ} # Can use any env variable. List in runtipi/templates/env-sample - - DNS_IP=${DNS_IP} + dns: + - ${DNS_IP} volumes: - ${APP_DATA_DIR}/data/config:/config #Always start the path with ${APP_DATA_DIR}. This will put all data inside app-data/my-app/data ports: diff --git a/packages/dashboard/src/components/Form/validators.ts b/packages/dashboard/src/components/Form/validators.ts index cd5c8b74..1205c0bb 100644 --- a/packages/dashboard/src/components/Form/validators.ts +++ b/packages/dashboard/src/components/Form/validators.ts @@ -6,21 +6,58 @@ export const validateAppConfig = (values: Record, fields: (AppCo fields.forEach((field) => { if (field.required && !values[field.id]) { - errors[field.id] = 'Field required'; - } else if (values[field.id] && field.min && values[field.id].length < field.min) { - errors[field.id] = `Field must be at least ${field.min} characters long`; - } else if (values[field.id] && field.max && values[field.id].length > field.max) { - errors[field.id] = `Field must be at most ${field.max} characters long`; - } else if (values[field.id] && field.type === FieldTypes.number && !validator.isNumeric(values[field.id])) { - errors[field.id] = 'Field must be a number'; - } else if (values[field.id] && field.type === FieldTypes.email && !validator.isEmail(values[field.id])) { - errors[field.id] = 'Field must be a valid email'; - } else if (values[field.id] && field.type === FieldTypes.fqdn && !validator.isFQDN(values[field.id] || '')) { - errors[field.id] = 'Field must be a valid domain'; - } else if (values[field.id] && field.type === FieldTypes.ip && !validator.isIP(values[field.id])) { - errors[field.id] = 'Field must be a valid IP address'; - } else if (values[field.id] && field.type === FieldTypes.fqdnip && !validator.isFQDN(values[field.id] || '') && !validator.isIP(values[field.id])) { - errors[field.id] = 'Field must be a valid domain or IP address'; + errors[field.id] = `${field.label} is required`; + } + + if (values[field.id]) { + switch (field.type) { + case FieldTypes.text: + if (field.max && values[field.id].length > field.max) { + errors[field.id] = `${field.label} must be less than ${field.max} characters`; + } + + if (field.min && values[field.id].length < field.min) { + errors[field.id] = `${field.label} must be at least ${field.min} characters`; + } + break; + case FieldTypes.password: + if (!validator.isLength(values[field.id], { min: field.min, max: field.max })) { + errors[field.id] = `${field.label} must be between ${field.min} and ${field.max} characters`; + } + break; + case FieldTypes.email: + if (!validator.isEmail(values[field.id])) { + errors[field.id] = `${field.label} must be a valid email address`; + } + break; + case FieldTypes.number: + if (!validator.isNumeric(values[field.id])) { + errors[field.id] = `${field.label} must be a number`; + } + break; + case FieldTypes.fqdn: + if (!validator.isFQDN(values[field.id])) { + errors[field.id] = `${field.label} must be a valid domain`; + } + break; + case FieldTypes.ip: + if (!validator.isIP(values[field.id])) { + errors[field.id] = `${field.label} must be a valid IP address`; + } + break; + case FieldTypes.fqdnip: + if (!validator.isFQDN(values[field.id] || '') && !validator.isIP(values[field.id])) { + errors[field.id] = `${field.label} must be a valid domain or IP address`; + } + break; + case FieldTypes.url: + if (!validator.isURL(values[field.id])) { + errors[field.id] = `${field.label} must be a valid URL`; + } + break; + default: + break; + } } }); diff --git a/packages/dashboard/src/core/types.ts b/packages/dashboard/src/core/types.ts index 0d4e8e0a..1c1069a9 100644 --- a/packages/dashboard/src/core/types.ts +++ b/packages/dashboard/src/core/types.ts @@ -6,6 +6,7 @@ export enum FieldTypes { fqdn = 'fqdn', ip = 'ip', fqdnip = 'fqdnip', + url = 'url', } interface FormField { From 3a3028067a0ddc1cc29951d4fb3e0b2ae518d3d5 Mon Sep 17 00:00:00 2001 From: Nicolas Meienberger Date: Mon, 23 May 2022 20:53:26 +0000 Subject: [PATCH 2/3] Improve validate config flow --- .../src/components/Form/validators.ts | 113 +++++++++--------- 1 file changed, 59 insertions(+), 54 deletions(-) diff --git a/packages/dashboard/src/components/Form/validators.ts b/packages/dashboard/src/components/Form/validators.ts index 1205c0bb..cdba3603 100644 --- a/packages/dashboard/src/components/Form/validators.ts +++ b/packages/dashboard/src/components/Form/validators.ts @@ -1,64 +1,69 @@ import validator from 'validator'; import { AppConfig, FieldTypes } from '../../core/types'; +const validateField = (field: AppConfig['form_fields'][0], value: string): string | undefined => { + if (field.required && !value) { + return `${field.label} is required`; + } + + if (!value) { + return; + } + + switch (field.type) { + case FieldTypes.text: + if (field.max && value.length > field.max) { + return `${field.label} must be less than ${field.max} characters`; + } + if (field.min && value.length < field.min) { + return `${field.label} must be at least ${field.min} characters`; + } + break; + case FieldTypes.password: + if (!validator.isLength(value, { min: field.min, max: field.max })) { + return `${field.label} must be between ${field.min} and ${field.max} characters`; + } + break; + case FieldTypes.email: + if (!validator.isEmail(value)) { + return `${field.label} must be a valid email address`; + } + break; + case FieldTypes.number: + if (!validator.isNumeric(value)) { + return `${field.label} must be a number`; + } + break; + case FieldTypes.fqdn: + if (!validator.isFQDN(value)) { + return `${field.label} must be a valid domain`; + } + break; + case FieldTypes.ip: + if (!validator.isIP(value)) { + return `${field.label} must be a valid IP address`; + } + break; + case FieldTypes.fqdnip: + if (!validator.isFQDN(value || '') && !validator.isIP(value)) { + return `${field.label} must be a valid domain or IP address`; + } + break; + case FieldTypes.url: + if (!validator.isURL(value)) { + return `${field.label} must be a valid URL`; + } + break; + default: + break; + } +}; + export const validateAppConfig = (values: Record, fields: (AppConfig['form_fields'][0] & { id: string })[]) => { const errors: any = {}; fields.forEach((field) => { - if (field.required && !values[field.id]) { - errors[field.id] = `${field.label} is required`; - } - - if (values[field.id]) { - switch (field.type) { - case FieldTypes.text: - if (field.max && values[field.id].length > field.max) { - errors[field.id] = `${field.label} must be less than ${field.max} characters`; - } - - if (field.min && values[field.id].length < field.min) { - errors[field.id] = `${field.label} must be at least ${field.min} characters`; - } - break; - case FieldTypes.password: - if (!validator.isLength(values[field.id], { min: field.min, max: field.max })) { - errors[field.id] = `${field.label} must be between ${field.min} and ${field.max} characters`; - } - break; - case FieldTypes.email: - if (!validator.isEmail(values[field.id])) { - errors[field.id] = `${field.label} must be a valid email address`; - } - break; - case FieldTypes.number: - if (!validator.isNumeric(values[field.id])) { - errors[field.id] = `${field.label} must be a number`; - } - break; - case FieldTypes.fqdn: - if (!validator.isFQDN(values[field.id])) { - errors[field.id] = `${field.label} must be a valid domain`; - } - break; - case FieldTypes.ip: - if (!validator.isIP(values[field.id])) { - errors[field.id] = `${field.label} must be a valid IP address`; - } - break; - case FieldTypes.fqdnip: - if (!validator.isFQDN(values[field.id] || '') && !validator.isIP(values[field.id])) { - errors[field.id] = `${field.label} must be a valid domain or IP address`; - } - break; - case FieldTypes.url: - if (!validator.isURL(values[field.id])) { - errors[field.id] = `${field.label} must be a valid URL`; - } - break; - default: - break; - } - } + errors[field.id] = validateField(field, values[field.id]); }); return errors; From 942f566a6019375f2c13dc9573273d775a1c09e1 Mon Sep 17 00:00:00 2001 From: Nicolas Meienberger Date: Mon, 23 May 2022 20:56:09 +0000 Subject: [PATCH 3/3] Fix Homarr source url --- apps/homarr/config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/homarr/config.json b/apps/homarr/config.json index 8c7e97ce..d859784e 100644 --- a/apps/homarr/config.json +++ b/apps/homarr/config.json @@ -5,8 +5,8 @@ "id": "homarr", "description": "A homepage for your server.", "short_desc": "Homarr is a simple and lightweight homepage for your server, that helps you easily access all of your services in one place.", - "author": "https://github.com/ajnart/", - "source": "https://github.com/ajnart/homar", + "author": "ajnart", + "source": "https://github.com/ajnart/homarr", "website": "https://discord.gg/C2WTXkzkwK", "image": "https://raw.githubusercontent.com/ajnart/homarr/master/public/imgs/logo.png", "form_fields": {}