Reimplemented XML Tools and added styling #227

Merged
bema merged 18 commits from bema/func/styling into master 2023-06-16 14:38:55 +02:00
21 changed files with 497 additions and 73 deletions

View File

@@ -8,6 +8,7 @@
"name": "new-frontend",
"version": "0.0.0",
"dependencies": {
"hljs": "^6.2.3",
"vue": "^3.3.4",
"vue-router": "^4.2.2"
},
@@ -2356,6 +2357,14 @@
"he": "bin/he"
}
},
"node_modules/hljs": {
"version": "6.2.3",
"resolved": "https://registry.npmjs.org/hljs/-/hljs-6.2.3.tgz",
"integrity": "sha512-2vtAOX8kI7WO4/19XPFl7WJauIGsOxZkD+6LLmDWx6IQsPvxjnqqFsJlfg+wkghrb5I59OS5oeqGU7Ihbp+oOw==",
"engines": {
"node": "*"
}
},
"node_modules/hosted-git-info": {
"version": "2.8.9",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",

View File

@@ -12,6 +12,7 @@
"format": "prettier --write src/"
},
"dependencies": {
"hljs": "^6.2.3",
"vue": "^3.3.4",
"vue-router": "^4.2.2"
},

View File

@@ -1,21 +1,14 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { RouterView } from 'vue-router';
import SidebarComponent from '@components/sidebar/SidebarComponent.vue';
const activeToolBox = ref('');
onMounted(() => {
activeToolBox.value = "xml";
});
</script>
<template>
<div id="layout" class="flex dark:bg-gray-700">
<div id="layout" class="flex bg-gradient-to-r from-white to-blue-200 dark:from-slate-800 dark:to-indigo-950">
<SidebarComponent />
<div class="relative p-12 w-11/12">
<div class="relative p-6 w-full m-4 bg-indigo-50 dark:bg-gray-700 rounded-2xl shadow-md">
<RouterView></RouterView>
</div>
</div>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<library>
<libraryName>City library</libraryName>
<libraryID>345123</libraryID>
<readerList>
<person>
<readerID>7321</readerID>
<name>Adam</name>
<surname>Choke</surname>
</person>
<person>
<readerID>5123</readerID>
<name>Lauren</name>
<surname>Wong</surname>
</person>
</readerList>
<bookList>
<book>
<bookID>6422</bookID>
<title>Harry Potter</title>
<readerID>7542</readerID>
</book>
<book>
<bookID>1234</bookID>
<title>Macbeth</title>
<readerID>5123</readerID>
</book>
<book>
<bookID>9556</bookID>
<title>Romeo and Juliet</title>
</book>
</bookList>
</library>

View File

@@ -0,0 +1,7 @@
declare namespace p="http://www.release11.com/person";
declare namespace b="http://www.release11.com/book";
declare namespace l="http://www.release11.com/library";
for $x in //p:person
return string($x/p:name)

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<l:library xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.release11.com" xmlns:l="http://www.release11.com/library" xmlns:p="http://www.release11.com/person" xmlns:b="http://www.release11.com/book">
<l:libraryName>City library</l:libraryName>
<l:libraryID>345123</l:libraryID>
<l:readerList>
<p:person>
<p:readerID>7321</p:readerID>
<p:name>Adam</p:name>
<p:surname>Choke</p:surname>
</p:person>
<p:person>
<p:readerID>5123</p:readerID>
<p:name>Lauren</p:name>
<p:surname>Wong</p:surname>
</p:person>
</l:readerList>
<l:bookList>
<b:book>
<b:bookID>6422</b:bookID>
<b:title>Harry Potter</b:title>
<p:readerID>7542</p:readerID>
</b:book>
<b:book>
<b:bookID>1234</b:bookID>
<b:title>Macbeth</b:title>
<p:readerID>5123</p:readerID>
</b:book>
<b:book>
<b:bookID>9556</b:bookID>
<b:title>Romeo and Juliet</b:title>
</b:book>
</l:bookList>
</l:library>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
targetNamespace="">
<xsd:element name="library">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element minOccurs="0" name="libraryName" type="xsd:string" />
<xsd:element minOccurs="0" name="libraryID" type="xsd:int" />
<xsd:element minOccurs="0" name="readerList">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element maxOccurs="unbounded" name="person">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element minOccurs="0" name="readerID" type="xsd:int" />
<xsd:element minOccurs="0" name="name" type="xsd:normalizedString" />
<xsd:element minOccurs="0" name="surname" type="xsd:normalizedString" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element minOccurs="0" name="bookList">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element maxOccurs="unbounded" name="book">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element minOccurs="0" name="bookID" type="xsd:int" />
<xsd:element minOccurs="0" name="title" type="xsd:string" />
<xsd:element minOccurs="0" name="readerID" type="xsd:int" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>

View File

@@ -0,0 +1,14 @@
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:b="http://www.release11.com/book" xmlns:p="http://www.release11.com/person"
xmlns:l="http://www.release11.com/library">
<xsl:template match="/">
<Library>
<ReaderCount>
<xsl:value-of select="count(//p:person)" />
</ReaderCount>
<BookCount>
<xsl:value-of select="count(/l:library/l:bookList/b:book)" />
</BookCount>
</Library>
</xsl:template>
</xsl:stylesheet>

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref , onMounted } from 'vue'
import { ref , onMounted} from 'vue'
import SidebarToolLinkComponent from './SidebarToolLinkComponent.vue';
import SidebarMenuElementComponent from './SidebarMenuElementComponent.vue';
import logoDark from '@assets/logo_biale.svg';
@@ -7,49 +7,47 @@ import logoWhite from '@assets/logo_czarne.svg';
const logoR11 = ref( logoDark );
function changeLogoForTheme(){
logoR11.value = isDarkModeSet() ? logoDark : logoWhite;
}
function isDarkModeSet(){
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
}
onMounted( () => {
changeLogoForTheme();
} )
function changeLogoForTheme(){
if (isDarkModeSet()) {
logoR11.value = logoDark;
} else{
logoR11.value = logoWhite;
}
}
})
</script>
<template>
<aside class="relative top-0 left-0 z-40 w-1/12 h-screen transition-transform -translate-x-full sm:translate-x-0" >
<div class="h-full px-3 py-4 overflow-y-auto bg-gray-100 dark:bg-gray-800">
<aside class="relative flex-shrink-0 top-0 left-0 z-40 w-48 h-screen" >
<div class="h-full px-3 pt-2 pb-4 overflow-y-auto">
<a href="https://release11.com/">
<img :src="logoR11" class="w-72 h-16 p-2 dark:bg-gray-800"/>
<img :src="logoR11" class="w-72 h-16 p-2 pt-0"/>
</a>
<ul class="space-y-2 font-medium">
<div class="flex flex-col font-medium items-center">
<sidebar-menu-element-component category-name="XML">
<li><SidebarToolLinkComponent path-to="/xml/xslt" element-content="XSLT" /></li>
<li><SidebarToolLinkComponent path-to="/xml/xpath" element-content="XPath" /></li>
<li><SidebarToolLinkComponent path-to="/xml/xsd" element-content="XSD" /></li>
<li><SidebarToolLinkComponent path-to="/xml/xquery" element-content="XQuery" /></li>
<SidebarToolLinkComponent path-to="/xml/xpath" element-content="XPath" />
<SidebarToolLinkComponent path-to="/xml/xquery" element-content="XQuery" />
<SidebarToolLinkComponent path-to="/xml/xsd" element-content="XSD" />
<SidebarToolLinkComponent path-to="/xml/xslt" element-content="XSLT" />
</sidebar-menu-element-component>
<sidebar-menu-element-component category-name="Formatter">
<li><SidebarToolLinkComponent path-to="/format/XML" element-content="XML Formatter" /></li>
<li><SidebarToolLinkComponent path-to="/format/HTML" element-content="HTML Formatter" /></li>
<li><SidebarToolLinkComponent path-to="/format/JSON" element-content="JSON Formatter" /></li>
<SidebarToolLinkComponent path-to="/format/HTML" element-content="HTML Formatter" />
<SidebarToolLinkComponent path-to="/format/JSON" element-content="JSON Formatter" />
<SidebarToolLinkComponent path-to="/format/XML" element-content="XML Formatter" />
</sidebar-menu-element-component>
<li><SidebarToolLinkComponent class="text-left" path-to="/rest/mock" element-content="REST Mock" /></li>
</ul>
<sidebar-menu-element-component category-name="REST">
<SidebarToolLinkComponent path-to="/rest/mock" element-content="Mock" />
</sidebar-menu-element-component>
</div>
</div>
</aside>
</template>

View File

@@ -1,13 +1,9 @@
<script setup lang="ts">
import { ref } from 'vue'
const hiddenOrActive = ref('hidden');
const isActive = ref(true);
function switchHiddenElement(){
if(hiddenOrActive.value == 'hidden'){
hiddenOrActive.value = "active";
} else{
hiddenOrActive.value = "hidden"
}
isActive.value = !isActive.value;
}
const props = defineProps(
@@ -21,12 +17,12 @@ const props = defineProps(
<template>
<li>
<button @click="switchHiddenElement()" type="button" class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700">
<span class="flex-1 ml-3 text-left whitespace-nowrap">{{props.categoryName}}</span>
<div class="w-full mb-4 p-2 rounded-xl shadow-md bg-gradient-to-r from-blue-400 to-blue-200 dark:from-sky-700 dark:to-sky-900">
<button @click="switchHiddenElement()" type="button" :class="[isActive ? 'rounded-lg' : 'rounded-lg']" class="w-full p-2 text-lg font-bold text-gray-900 transition duration-75 hover:bg-blue-100 dark:text-gray-100 dark:hover:bg-slate-600">
<span class="flex-1 whitespace-nowrap">{{props.categoryName}}</span>
</button>
<ul class='py-2 space-y-2 bg-gray-50 dark:bg-gray-700 rounded-xl' :class="hiddenOrActive">
<div class="flex flex-col w-full py-2 bg-indigo-50 dark:bg-slate-800 rounded-xl font-thin overflow-hidden" :class="[isActive ? 'active' : 'hidden']">
<slot></slot>
</ul>
</li>
</div>
</div>
</template>

View File

@@ -2,13 +2,21 @@
import { RouterLink } from 'vue-router';
const props = defineProps(
{
elementContent: {required: false},
pathTo: {type: String, required:true}
elementContent: { required: false },
pathTo: { type: String, required: true }
}
)
</script>
<template>
<RouterLink class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700" :to="props.pathTo">{{ props.elementContent }}</RouterLink>
</template>
<RouterLink
class="w-full text-center py-2 px-4 text-gray-800 transition duration-75 hover:bg-blue-100 dark:text-white dark:hover:bg-slate-600"
:to="props.pathTo">{{ props.elementContent }}</RouterLink>
</template>
<style>
.router-link-active {
font-weight: 500;
}
</style>

View File

@@ -1,23 +1,47 @@
<script setup lang="ts">
import xmlInputFieldToolbarComponent from '@/components/xml/XmlInputFieldToolbarComponent.vue';
import { ref } from 'vue';
const xml = ref('')
const query = ref('')
const props = defineProps(
{
transformationName: {type: String},
prettyName: {type: String, required: true},
xmlData: {type: String},
}
)
const emit = defineEmits(['update:xml', 'update:transform'])
function sendXml() {
emit('update:xml', xml.value)
}
function sendTransform() {
emit('update:transform', query.value)
}
function setToDefaultXML(data: string) {
xml.value = data;
sendXml();
}
function setToDefaultQuery(data: string) {
query.value = data;
sendTransform();
}
</script>
<template>
<div class="flex flex-col gap-6 w-full h-full items-center">
<label for="xmlfield" class="dark:text-white">XML</label>
<textarea id="xmlfield" class="w-1/2 h-36 bg-gray-500">
</textarea>
<label for="transformField" class="dark:text-white">{{ props.transformationName }}</label>
<textarea id="transformField" class="w-1/2 h-36 bg-gray-500">
</textarea>
<div class="flex flex-col w-full lg:w-1/2 h-full items-center gap-4">
<div class="flex flex-col w-full h-1/2">
<xmlInputFieldToolbarComponent prettyName="XML" @update:defaultData="(data) => setToDefaultXML(data)"></xmlInputFieldToolbarComponent>
<textarea id="xmlField" v-model="xml" @input="sendXml()" class="w-full h-full resize-none dark:text-slate-100 dark:bg-gray-600 border border-slate-400 p-2 rounded-md"></textarea>
</div>
<div class="flex flex-col w-full h-1/2">
<xmlInputFieldToolbarComponent :prettyName="$props.prettyName" @update:defaultData="(data) => setToDefaultQuery(data)"></xmlInputFieldToolbarComponent>
<textarea id="transformField" v-model="query" @input="sendTransform()" class="w-full h-full resize-none dark:text-slate-100 dark:bg-gray-600 border border-slate-400 p-2 rounded-md"></textarea>
</div>
</div>
</template>

View File

@@ -0,0 +1,50 @@
<script setup lang="ts">
import sampleXML from "@/assets/sampleXml.xml?raw"
import sampleXSLT from "@/assets/sampleXslt.xml?raw"
import sampleXSD from "@/assets/sampleXsd.xml?raw"
import sampleXQuery from "@/assets/sampleXQuery.xquery?raw"
const props = defineProps(
{
prettyName: {type: String, required: true}
}
)
const emit = defineEmits(['update:defaultData'])
function setDefault() {
const emitName = "update:defaultData";
switch (props.prettyName.toLowerCase()) {
case "xpath":
emit(emitName, "string(/l:library/l:libraryName)")
break;
case "xsd":
emit(emitName, sampleXSD)
break;
case "xslt":
emit(emitName, sampleXSLT)
break;
case "xquery":
emit(emitName, sampleXQuery)
break;
default:
emit(emitName, sampleXML)
break;
}
}
</script>
<template>
<div class="flex place-content-between w-full pr-2 items-center m-2">
<span class="dark:text-white">{{ prettyName }}</span>
<div class="flex space-x-2">
<button class="tool-button" @click="setDefault()">Insert default {{ prettyName }}</button>
</div>
</div>
</template>

View File

@@ -0,0 +1,30 @@
<script setup lang="ts">
import xmlOutputFieldToolbarComponent from '@/components/xml/XmlOutputFieldToolbarComponent.vue';
import { ref } from 'vue';
const props = defineProps(
{
tool: {type: String, required: true},
xml: {type: String},
query: {type: String}
}
)
const result = ref('');
function parseResult(data: any) {
result.value = data.result;
}
</script>
<template>
<div class="flex flex-col w-full lg:w-1/2 h-full items-center">
<xmlOutputFieldToolbarComponent :xml="$props.xml" :query="$props.query" :tool="$props.tool" @update:result="(data) => parseResult(data)"></xmlOutputFieldToolbarComponent>
<div class="w-full h-full p-2 overflow-scroll border border-slate-400 rounded-md text-left bg-white dark:text-slate-100 dark:bg-gray-600">
<pre class="break-words"><code>{{ result }}</code></pre>
</div>
</div>
</template>

View File

@@ -0,0 +1,112 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue';
var engines = ["saxon", "xalan", "libxml"];
var versions = ["1.0", "2.0", "3.0", "3.1"];
const props = defineProps(
{
tool: {type: String, required: true},
xml: {type: String},
query: {type: String},
}
)
const emit = defineEmits(['update:result'])
const engine = ref('');
const version = ref('');
const isSaxonHidden = ref(false);
const isXalanHidden = ref(false);
const isLibXMLHidden = ref(false);
onMounted(() => {
selectAvailableEngines();
selectAvailableVersions();
selectDefaults();
})
function selectAvailableEngines() {
if (props.tool == "xsd") {
engines = ["xalan", "libxml"]
}
else if (props.tool == "xquery") {
engines = ["saxon"]
}
}
function selectAvailableVersions() {
if (props.tool == "xquery")
versions = ["3.1"];
else if (props.tool == "xsd")
versions = ["N/A"];
}
function selectDefaults() {
version.value = versions[versions.length - 1];
engine.value = engines[0];
}
function process() {
var request:Request = prepareRequest();
fetchRequest(request).then((data) => {
sendProcessedData(data);
})
}
function prepareRequest():Request {
var request = new Request(prepareURL(), {
body: prepareRequestBody(),
method: "POST"
});
return request
}
function prepareURL(): string {
const engineEndpoint = engine.value == "libxml" ? "libxml" : "java";
return document.location.protocol + "//" + document.location.hostname + "/" + engineEndpoint + "/" + props.tool;
}
function prepareRequestBody():string {
var requestBody = JSON.stringify({
"data": props.xml,
"process": props.query,
"processor": engine.value,
"version": version.value
});
return requestBody;
}
async function fetchRequest(request: Request):Promise<JSON> {
var responseBody = await fetch(request)
.then(response => response.json())
.then((body) => body);
return responseBody;
}
function sendProcessedData(data: JSON) {
emit("update:result", data);
}
</script>
<template>
<div class="flex place-content-between w-full items-center m-2">
<span class="dark:text-white">Result:</span>
<div class="flex space-x-2">
<select v-model="engine" name="engine" class="px-3 rounded-full border border-slate-400 bg-white dark:text-slate-100 dark:bg-gray-600">
<option v-for="engine in engines" :value="engine">{{ engine }}</option>
</select>
<select v-model="version" name="version" class="px-3 rounded-full border border-slate-400 bg-white dark:text-slate-100 dark:bg-gray-600">
<option v-for="version in versions" :value="version">{{ version }}</option>
</select>
<button class="tool-button">Clear</button>
<button class="tool-button" @click="process">Process</button>
</div>
</div>
</template>

View File

@@ -4,6 +4,9 @@ const landingPage = import("@views/LandingView.vue")
const restMock = import("@views/RestMockView.vue")
const xsltTool = import("@views/XSLTView.vue")
const xsdTool = import("@views/XSDView.vue")
const xpathTool = import("@views/XPathView.vue")
const xqueryTool = import("@views/XQueryView.vue")
const routes = [
{
@@ -11,16 +14,26 @@ const routes = [
name: 'landing',
component: () => landingPage
},
{
path: '/xml/xpath',
name: 'xpath',
component: () => xpathTool
},
{
path: '/xml/xquery',
name: 'xquery',
component: () => xqueryTool
},
{
path: '/xml/xsd',
name: 'xsd',
component: () => xsdTool
},
{
path: '/xml/xslt',
name: 'xslt',
component: () => xsltTool
},
{
path: '/xml/xpath',
name: 'xpath',
component: () => restMock
},
]

View File

@@ -1,3 +1,7 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
.tool-button {
@apply py-1 px-4 rounded-full bg-gradient-to-r from-blue-300 to-sky-200 dark:text-white dark:from-sky-600 dark:to-sky-800 hover:bg-blue-400
}

View File

@@ -0,0 +1,18 @@
<script setup lang="ts">
import xmlInputFieldComponent from '@/components/xml/XmlInputFieldComponent.vue';
import xmlOutputFieldComponent from '@/components/xml/XmlOutputFieldComponent.vue';
import { ref } from 'vue';
const xml = ref('');
const query = ref('');
</script>
<template>
<div id="layout" class="flex flex-col lg:flex-row w-full h-full gap-4">
<xmlInputFieldComponent prettyName="XPath" @update:xml="(data) => {xml = data}" @update:transform="(data) => {query = data}"></xmlInputFieldComponent>
<xmlOutputFieldComponent tool="xpath" :xml="xml" :query="query"></xmlOutputFieldComponent>
</div>
</template>

View File

@@ -0,0 +1,18 @@
<script setup lang="ts">
import xmlInputFieldComponent from '@/components/xml/XmlInputFieldComponent.vue';
import xmlOutputFieldComponent from '@/components/xml/XmlOutputFieldComponent.vue';
import { ref } from 'vue';
const xml = ref('');
const query = ref('');
</script>
<template>
<div id="layout" class="flex flex-col lg:flex-row w-full h-full gap-4">
<xmlInputFieldComponent prettyName="XQuery" @update:xml="(data) => {xml = data}" @update:transform="(data) => {query = data}"></xmlInputFieldComponent>
<xmlOutputFieldComponent tool="xquery" :xml="xml" :query="query"></xmlOutputFieldComponent>
</div>
</template>

View File

@@ -0,0 +1,18 @@
<script setup lang="ts">
import xmlInputFieldComponent from '@/components/xml/XmlInputFieldComponent.vue';
import xmlOutputFieldComponent from '@/components/xml/XmlOutputFieldComponent.vue';
import { ref } from 'vue';
const xml = ref('');
const query = ref('');
</script>
<template>
<div id="layout" class="flex flex-col lg:flex-row w-full h-full gap-4">
<xmlInputFieldComponent prettyName="XSD" @update:xml="(data) => {xml = data}" @update:transform="(data) => {query = data}"></xmlInputFieldComponent>
<xmlOutputFieldComponent tool="xsd" :xml="xml" :query="query"></xmlOutputFieldComponent>
</div>
</template>

View File

@@ -1,15 +1,18 @@
<script lang="ts">
<script setup lang="ts">
import xmlInputFieldComponent from '@/components/xml/XmlInputFieldComponent.vue';
import xmlOutputFieldComponent from '@/components/xml/XmlOutputFieldComponent.vue';
import { ref } from 'vue';
export default {
name: "XSLT",
components: {xmlInputFieldComponent}
}
const xml = ref('');
const query = ref('');
</script>
<template>
<div id="layout" class="flex flex-col lg:flex-row w-full h-full gap-4">
<xmlInputFieldComponent prettyName="XSLT" @update:xml="(data) => {xml = data}" @update:transform="(data) => {query = data}"></xmlInputFieldComponent>
<xmlInputFieldComponent transformationName="XSLT"></xmlInputFieldComponent>
<xmlOutputFieldComponent tool="xslt" :xml="xml" :query="query"></xmlOutputFieldComponent>
</div>
</template>