diff options
Diffstat (limited to 'lib/admin/src/feedProperties/index.ts')
-rw-r--r-- | lib/admin/src/feedProperties/index.ts | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/lib/admin/src/feedProperties/index.ts b/lib/admin/src/feedProperties/index.ts new file mode 100644 index 0000000..733acde --- /dev/null +++ b/lib/admin/src/feedProperties/index.ts @@ -0,0 +1,144 @@ +// 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 <https://www.gnu.org/licenses/>. + +import { cloneDeep, filter, forEach, isEmpty, join, map } from 'lodash'; +import { watch, Ref, ref } from 'vue'; +import { FeedProperty, XmlPropertyContainer } from '../types'; + +/** + * An interface for working with xml properties from an xml feed + */ +export interface UseXmlProperties { + + /** + * Correctly formats and exports the current properties + */ + getCurrentProperties(): FeedProperty[] | undefined; + + /** + * Gets the current properties as xml + */ + getXml(): string | undefined; + + /** + * Saves properties values from a json string + * @param json The property json to parse + * @returns True if the json was parsed and saved, false otherwise + */ + saveJson: (json: string | undefined) => boolean; + + /** + * Gets a copy of the current properties + */ + getModel(): FeedProperty[] | undefined; + + /** + * Manually adds an array of properties to the current properties + */ + addProperties: (properties: FeedProperty[]) => void; +} + +/** + * Creates a new instance of the useXmlProperties api from the given feed + * @param feed The feed to read and watch for changes from + * @returns An api for working with xml properties + */ +export const useXmlProperties = <T extends XmlPropertyContainer>(feed: Ref<T | undefined>): UseXmlProperties => { + + //The current properties + const currentProperties = ref<FeedProperty[]>(feed.value?.properties || []); + + //Watch for changes to the feed + watch(feed, (newFeed) => { currentProperties.value = newFeed?.properties || [] }, { immediate: true }); + + const getCurrentProperties = (): FeedProperty[] | undefined => { + //Get all properties that are not emtpy + return filter(currentProperties.value, p => !isEmpty(p.name)); + } + + const getPropertyXml = (properties: FeedProperty[]): string => { + let output = ''; + forEach(properties, prop => { + //Open tag (with namespace if present) + output += !isEmpty(prop.namespace) ? `<${prop.namespace}:${prop.name}` : `<${prop.name}` + + if (!isEmpty(prop.attributes)) { + forEach(prop.attributes, (value, key) => output += ` ${key}="${value}"`) + } + + //Recursive call for nested property, or add its value + output += !isEmpty(prop.properties) ? `>${getPropertyXml(prop.properties!)}` : `>${prop.value || ''}` + + //Close tag + output += !isEmpty(prop.namespace) ? `</${prop.namespace}:${prop.name}>` : `</${prop.name}>` + return output; + }) + return output; + } + + const getModel = (): FeedProperty[] | undefined => { + return cloneDeep(currentProperties.value); + } + + const getXml = (): string => { + if (currentProperties.value === undefined) { + return ''; + } + return join(map(currentProperties.value, p => getPropertyXml([p])), '\n'); + } + + const saveJson = (json: string | undefined): boolean => { + + if (isEmpty(json)) { + //Clear all properties if json is undefined + currentProperties.value = []; + return true + } + + try { + const parsed = JSON.parse(json!); + + const props = map(parsed, (prop) => ({ + name: prop.name, + value: prop.value, + namespace: prop.namespace, + attributes: prop.attributes, + properties: prop.properties + })) + + //Remove any empty properties + const nonEmpty = filter(props, p => !isEmpty(p.name)); + + //Set the properties + currentProperties.value = nonEmpty; + + return true; + } catch (err) { + return false; + } + } + + const addProperties = (properties: FeedProperty[]) => { + currentProperties.value = [...currentProperties.value, ...properties]; + } + + return { + getCurrentProperties, + getXml, + saveJson, + getModel, + addProperties + } +}
\ No newline at end of file |