// Copyright (C) 2023 Vaughn Nugent
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
import { MaybeRef, computed, watch, Ref } from 'vue'
import { helpers, required, maxLength, numeric } from "@vuelidate/validators"
import { useVuelidateWrapper } from '@vnuge/vnlib.browser';
import { BlogChannel, ChannelFeed } from '@vnuge/cmnext-admin';
import useVuelidate from "@vuelidate/core"
export const getChannelForm = (editMode?: Ref) => {
const channelSchema = computed(() => {
return {
fields: [
{
id: 'channel-name',
type: 'text',
label: 'Channel Name',
name: 'name',
placeholder: 'Enter the name of the channel',
description: 'A simple human readable name for the channel'
},
{
id: 'channel-path',
type: 'text',
label: 'Root Path',
name: 'path',
placeholder: 'Enter the root path to the channel',
description: editMode?.value ? 'You may not edit the channel directory' : 'The path in your bucket to the working directory for the channel',
disabled: editMode?.value
},
{
id: 'channel-index',
type: 'text',
label: 'Index File',
name: 'index',
placeholder: 'Enter the index file for the channel',
description: editMode?.value ?
'You may not edit the index file path'
: 'The name or path of the post index file, stored under the root directory of the channel',
disabled: editMode?.value
},
{
id: 'channel-content-dir',
type: 'text',
label: 'Content Directory',
name: 'content',
placeholder: 'Enter the content directory for the channel',
description: editMode?.value ?
'You may not edit the content directory path'
: 'The name or path of the content directory, stored under the root directory of the channel',
disabled: editMode?.value
},
{
id: 'index-file-example',
type: 'text',
label: 'Index Path',
name: 'example',
placeholder: 'Your index file path',
description: 'This is the location within your bucket where the index file will be stored',
disabled: true,
}
]
}
});
const feedSchema = {
fields: [
{
id: 'channel-feed-url',
type: 'text',
label: 'Publish Url',
name: 'url',
placeholder: 'Enter the feed url for the channel',
description: 'The rss syndication url for your blog channel, the http url your blog resides at.'
},
{
id: 'channel-feed-path',
type: 'text',
label: 'Feed File',
name: 'path',
placeholder: 'feed.xml',
description: 'The path to the feed xml file within the channel directory'
},
{
id: 'channel-feed-image',
type: 'text',
label: 'Image Url',
name: 'image',
placeholder: 'Enter the url for the default feed image',
description: 'The full http url to the default feed image'
},
{
id: 'channel-feed-author',
type: 'text',
label: 'Feed Author',
name: 'author',
placeholder: 'Your name',
description: 'The author name for the feed'
},
{
id: 'channel-feed-contact',
type: 'text',
label: 'Feed Contact',
name: 'contact',
placeholder: 'Your contact email address',
description: 'The webmaster contact email address'
},
{
id: 'channel-feed-max-items',
type: 'number',
label: 'Feed Max Items',
name: 'maxItems',
placeholder: 'Enter the feed max items for the channel',
description: 'The maximum number of posts to publish in the feed'
},
{
id: 'channel-feed-description',
type: 'textarea',
label: 'Feed Description',
name: 'description',
placeholder: 'Enter the feed description for the channel',
}
]
}
const alphaNumSpace = helpers.regex(/^[a-zA-Z0-9 ]*$/);
const httpUrl = helpers.regex(/^(http|https):\/\/[^ "]+$/);
const channelRules = {
name: {
required: helpers.withMessage('Channel name is required', required),
maxlength: helpers.withMessage('Channel name must be less than 50 characters', maxLength(50)),
alphaNumSpace: helpers.withMessage('Channel name must be alphanumeric', alphaNumSpace),
},
path: {
required: helpers.withMessage('Channel path is required', required),
maxlength: helpers.withMessage('Channel path must be less than 50 characters', maxLength(50)),
},
index: {
required: helpers.withMessage('Channel index is required', required),
maxlength: helpers.withMessage('Channel index must be less than 50 characters', maxLength(50)),
},
content: {
required: helpers.withMessage('Channel content directory is required', required),
maxlength: helpers.withMessage('Channel content directory must be less than 50 characters', maxLength(50)),
},
example: {}
}
const feedRules = {
url: {
required: helpers.withMessage('Channel feed url is required', required),
maxlength: helpers.withMessage('Channel feed url must be less than 100 characters', maxLength(100)),
url: helpers.withMessage('Channel feed url must be a valid url', httpUrl),
},
path: {
required: helpers.withMessage('Channel feed path is required', required),
maxlength: helpers.withMessage('Channel feed path must be less than 50 characters', maxLength(50)),
},
image: {
maxlength: helpers.withMessage('Channel feed image must be less than 200 characters', maxLength(200)),
},
contact: {
maxlength: helpers.withMessage('Channel feed contact must be less than 50 characters', maxLength(50)),
},
description: {
alphaNumSpace: helpers.withMessage('Channel feed description must be alphanumeric', alphaNumSpace),
maxlength: helpers.withMessage('Channel feed description must be less than 50 characters', maxLength(200)),
},
maxItems: {
numeric: helpers.withMessage('Channel feed max items must be a number', numeric),
},
author: {
alphaNumSpace: helpers.withMessage('Channel feed author must be alphanumeric', alphaNumSpace),
maxlength: helpers.withMessage('Channel feed author must be less than 50 characters', maxLength(50)),
}
}
const getChannelValidator = (buffer: MaybeRef) => {
const v$ = useVuelidate(channelRules, buffer, { $lazy: true, $autoDirty: true });
const updateExample = () => {
if (!v$.value.path.$model || !v$.value.index.$model) {
v$.value.example.$model = '';
return;
}
//Update the example path
v$.value.example.$model = `${v$.value.path.$model}/${v$.value.index.$model}`;
}
watch(v$, updateExample);
updateExample();
const { validate } = useVuelidateWrapper(v$);
return { v$, validate, reset: v$.value.$reset };
}
const getFeedValidator = (buffer: MaybeRef) => {
const v$ = useVuelidate(feedRules, buffer, { $lazy: true, $autoDirty: true });
const { validate } = useVuelidateWrapper(v$);
return { v$, validate, reset: v$.value.$reset };
}
return {
channelSchema,
feedSchema,
channelRules,
feedRules,
getChannelValidator,
getFeedValidator
};
}