Merge branch 'master' of gitea.release11.com:R11/release11-tools into widlam/add_multiplefiles_xslt

This commit is contained in:
2023-12-01 12:19:32 +01:00
54 changed files with 639 additions and 315 deletions

View File

@@ -11,6 +11,6 @@ spring.redis.host=redis
spring.redis.port=6379
#retention
retention.minutes-to-delete-message=120
retention.minutes-to-delete-message=1440
retention.minutes-to-delete-history-record=1440
retention.retention-cooldown=1440

View File

@@ -36,7 +36,7 @@ public class JsonController implements RestController {
try {
Object requestJson = this.gson.fromJson(request.body(), Object.class);
responseJson.addProperty("data", this.prettyGson.toJson(requestJson));
responseJson.addProperty("result", this.prettyGson.toJson(requestJson));
responseJson.addProperty("time", System.currentTimeMillis() - startProcess);
@@ -46,7 +46,7 @@ public class JsonController implements RestController {
response.status(400);
responseJson.addProperty("data", cause == null ? e.getMessage() : cause.getMessage());
responseJson.addProperty("result", cause == null ? e.getMessage() : cause.getMessage());
responseJson.addProperty("time", System.currentTimeMillis() - startProcess);
@@ -65,17 +65,17 @@ public class JsonController implements RestController {
response.status(200);
responseJson.addProperty("data", this.gson.toJson(requestJson));
responseJson.addProperty("result", this.gson.toJson(requestJson));
responseJson.addProperty("time", System.currentTimeMillis() - startProcess);
response.body(this.gson.toJson(responseJson));
} catch (Exception e) {
this.logger.error("Error on minimizeing Json " + e);
this.logger.error("Error on minimizing Json " + e);
Throwable cause = e.getCause();
response.status(400);
responseJson.addProperty("data", cause == null ? e.getMessage() : cause.getMessage());
responseJson.addProperty("result", cause == null ? e.getMessage() : cause.getMessage());
responseJson.addProperty("time", System.currentTimeMillis() - startProcess);
response.body(this.prettyGson.toJson(responseJson));

View File

@@ -1,4 +1,4 @@
FROM node:latest as build-stage
FROM node:20.9.0-bullseye-slim as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
@@ -7,7 +7,7 @@ RUN npm run build
FROM nginx:stable-alpine as production-stage
FROM nginx:stable-alpine3.17-slim as production-stage
RUN mkdir /app
RUN apk add --no-cache tzdata
@@ -20,7 +20,7 @@ EXPOSE 80
EXPOSE 443
FROM node:latest as dev
FROM node:20.9.0-bullseye-slim as dev
WORKDIR /app
COPY package*.json ./
RUN npm install

View File

@@ -13,6 +13,7 @@
"@codemirror/lang-xml": "^6.0.2",
"@codemirror/theme-one-dark": "^6.1.2",
"codemirror": "^6.0.1",
"thememirror": "^2.0.1",
"vue": "^3.3.4",
"vue-codemirror": "^6.1.1",
"vue-router": "^4.2.2"
@@ -3190,9 +3191,9 @@
}
},
"node_modules/normalize-package-data/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true,
"bin": {
"semver": "bin/semver"
@@ -3326,9 +3327,9 @@
}
},
"node_modules/npm-run-all/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true,
"bin": {
"semver": "bin/semver"
@@ -3616,9 +3617,9 @@
}
},
"node_modules/postcss": {
"version": "8.4.24",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz",
"integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==",
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"funding": [
{
"type": "opencollective",
@@ -4305,6 +4306,16 @@
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
"dev": true
},
"node_modules/thememirror": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/thememirror/-/thememirror-2.0.1.tgz",
"integrity": "sha512-d5i6FVvWWPkwrm4cHLI3t9AT1OrkAt7Ig8dtdYSofgF7C/eiyNuq6zQzSTusWTde3jpW9WLvA9J/fzNKMUsd0w==",
"peerDependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0"
}
},
"node_modules/thenify": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
@@ -6994,9 +7005,9 @@
},
"dependencies": {
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true
}
}
@@ -7097,9 +7108,9 @@
"dev": true
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true
},
"shebang-command": {
@@ -7302,9 +7313,9 @@
"dev": true
},
"postcss": {
"version": "8.4.24",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz",
"integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==",
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"requires": {
"nanoid": "^3.3.6",
"picocolors": "^1.0.0",
@@ -7756,6 +7767,12 @@
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
"dev": true
},
"thememirror": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/thememirror/-/thememirror-2.0.1.tgz",
"integrity": "sha512-d5i6FVvWWPkwrm4cHLI3t9AT1OrkAt7Ig8dtdYSofgF7C/eiyNuq6zQzSTusWTde3jpW9WLvA9J/fzNKMUsd0w==",
"requires": {}
},
"thenify": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",

View File

@@ -17,6 +17,7 @@
"@codemirror/lang-xml": "^6.0.2",
"@codemirror/theme-one-dark": "^6.1.2",
"codemirror": "^6.0.1",
"thememirror": "^2.0.1",
"vue": "^3.3.4",
"vue-codemirror": "^6.1.1",
"vue-router": "^4.2.2"

View File

@@ -6,9 +6,9 @@ import SidebarComponent from '@components/sidebar/SidebarComponent.vue';
</script>
<template>
<div id="layout" class="flex h-screen bg-gradient-to-r from-white to-sky-200 dark:from-slate-800 dark:to-indigo-950">
<div id="layout" class="font-sans flex h-screen bg-gradient-to-br from-sky-200 to-indigo-200 dark:from-sky-950 dark:to-indigo-950">
<SidebarComponent />
<div class="relative p-4 w-full m-4 bg-blue-50 dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg">
<div class="relative p-4 w-full m-4 ml-0 bg-blue-50 dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg">
<RouterView></RouterView>
</div>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -2,11 +2,11 @@
"universalInfo":
[
{
"category":"What is XPath",
"category":"What is XPath?",
"description":"XPath is a query language used for selecting nodes from XML and processing them. It may perform operations on strings, numbers and boolean values."
},
{
"category":"What's new in XPath?"
"category":"What's new in XPath"
}
],
"VersionDiffs":

View File

@@ -6,7 +6,7 @@
"description":"XSLT (Extensible Stylesheet Language Transformations) is a language for converting and manipulating XML data into various formats. It uses rules defined in stylesheets to transform XML documents into HTML, XML, or other text-based outputs."
},
{
"category":"What's differences between XSLT versions"
"category":"Differences between XSLT versions"
}
],
"VersionDiffs":

View File

@@ -2,60 +2,72 @@
import { computed, ref } from 'vue'
import { Codemirror } from 'vue-codemirror'
import { oneDark } from '@codemirror/theme-one-dark'
import { espresso } from 'thememirror';
import {xml} from '@codemirror/lang-xml'
import {json} from '@codemirror/lang-json'
import {html} from '@codemirror/lang-html'
function isDarkModeSet(){
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
}
const props= defineProps({
code : {
type: String,
required: true
const props= defineProps({
code : {
type: String,
required: true
},
config: {
type: Object,
required: true
},
config: {
type: Object,
required: true
},
})
})
const emit = defineEmits(
[
'update:updatedCode'
]
)
const emit = defineEmits(
[
'update:updatedCode'
]
)
function dataUpdated(newData:String, viewUpdate : any){
emit('update:updatedCode',newData)
function dataUpdated(newData:String, viewUpdate : any){
emit('update:updatedCode',newData)
}
function selectTheme() {
if (isDarkModeSet()) {
return oneDark;
}
else {
return espresso;
}
}
const extensions = computed( ()=> {
return [
oneDark,
parseLanguage(props.config.language),
]
const extensions = computed( ()=> {
return [
selectTheme(),
parseLanguage(props.config.language),
]
} )
} )
function parseLanguage(name: String){
switch(name.toUpperCase()){
case "JSON": {
return json();
}
case "HTML": {
return html();
}
default: {
return xml();
}
function parseLanguage(name: String){
switch(name.toUpperCase()){
case "JSON": {
return json();
}
case "HTML": {
return html();
}
default: {
return xml();
}
}
}
</script>
<template>
<div class="editor w-full max-w-full h-full overflow-scroll">
<div class="editor w-full h-full rounded-2xl overflow-x-auto">
<codemirror
style="height: 100%; width: 100%; padding:1rem ; border-radius: 1rem; font-size: large;"

View File

@@ -3,7 +3,7 @@
const props = defineProps(
{
encodeType: {type:String,required:true},
operationType: {type:String,required:true},
code: {type: String, required: true}
}
)
@@ -15,16 +15,16 @@ const emit = defineEmits([
function convert(){
console.log("works")
switch(props.encodeType.toLowerCase()){
case "base64":{
switch(props.operationType.toLowerCase()){
case "encode":{
emit('update:result', btoa(props.code) )
break;
}
case "text":{
case "decode":{
emit('update:result', atob(props.code) )
break;
}
case "image":{
case "show image":{
emit('image:show', props.code )
break;
}
@@ -35,5 +35,5 @@ function convert(){
</script>
<template>
<button @click="convert()" class="tool-button">{{ props.encodeType }}</button>
<button @click="convert()" class="tool-button">{{ props.operationType }}</button>
</template>

View File

@@ -0,0 +1,114 @@
<script setup lang="ts">
import XMLButtonFormatterComponent from '@/components/formatter/XMLButtonFormatterComponent.vue';
import JsonButtonFormatterComponent from '@/components/formatter/JsonButtonFormatterComponent.vue';
import HtmlButtonFormatterComponent from '@/components/formatter/HtmlButtonFormatterComponent.vue';
import InsertTemplateComponent from '@components/common/InsertTemplateComponent.vue';
import CodeEditorComponent from '@/components/CodeEditorComponent.vue';
import { ref } from 'vue';
const data = ref('');
const inputFile = ref()
const errorOccurred = ref(false);
const successOccurred = ref(false);
const props = defineProps({
formatterLanguage: {
type: String,
required: true
}
})
function setTextFieldValue(newData: string) {
successOccurred.value = false;
errorOccurred.value = false;
data.value = newData;
}
function format(formatted: any) {
data.value = formatted.result;
}
function setErrorOccurred(occurred: boolean) {
errorOccurred.value = occurred;
successOccurred.value = !(occurred);
}
function setExample(data: string) {
inputFile.value.value = ''
setTextFieldValue(data)
}
function clear() {
data.value = '';
successOccurred.value = false;
errorOccurred.value = false;
inputFile.value.value = ''
}
function readFile(file : any) {
const reader = new FileReader()
reader.onloadend = () => {
var result = reader.result?.toString()
if (typeof result == "string")
setTextFieldValue(result);
}
reader.readAsText(file.target.files[0])
}
function highlightTextField() {
if (successOccurred.value)
return "text-field-success";
if (errorOccurred.value)
return "text-field-error";
return "";
}
</script>
<template>
<div id="layout" class="flex flex-col w-full h-full gap-4">
<div id="toolbar" class= "flex flex-col gap-4 items-center lg:flex-row place-content-between">
<span class="dark:text-slate-100"> {{ formatterLanguage }} Formatter</span>
<!-- XML Formatter Toolbar -->
<div v-if="formatterLanguage.toLowerCase() == 'xml'" class="flex flex-wrap gap-2 justify-center">
<div class="flex items-stretch w-64">
<input id="fileLoader" ref="inputFile" class="file-selector" type="file" accept=".xml,.xql,.xquery,.xslt,text/xml,text/plain" @change="readFile" />
</div>
<InsertTemplateComponent stylized-name="XML" @update:defaultData="(data: string) => setExample(data)"></InsertTemplateComponent>
<button class="tool-button" @click="clear()">Clear</button>
<XMLButtonFormatterComponent @update:error="setErrorOccurred" is-minimizer :xml="data" @update:result="format"></XMLButtonFormatterComponent>
<XMLButtonFormatterComponent @update:error="setErrorOccurred" :xml="data" @update:result="format"></XMLButtonFormatterComponent>
</div>
<!-- JSON Formatter Toolbar -->
<div v-if="formatterLanguage.toLowerCase() == 'json'" class="flex flex-wrap gap-2 justify-center">
<div class="flex items-stretch w-64">
<input id="fileLoader" ref="inputFile" class="file-selector" type="file" accept=".json,text/xml,text/plain,text/json,application/json" @change="readFile" />
</div>
<InsertTemplateComponent stylized-name="JSON" @update:defaultData="(data: string) => setExample(data)"></InsertTemplateComponent>
<button class="tool-button" @click="clear()">Clear</button>
<JsonButtonFormatterComponent isMinimizer :json="data" @update:result="format" @update:error="setErrorOccurred"></JsonButtonFormatterComponent>
<JsonButtonFormatterComponent :json="data" @update:result="format" @update:error="setErrorOccurred"></JsonButtonFormatterComponent>
</div>
<!-- HTML Formatter Toolbar -->
<div v-if="formatterLanguage.toLowerCase() == 'html'" class="flex flex-wrap gap-2 justify-center">
<div class="flex items-stretch w-64">
<input id="fileLoader" ref="inputFile" class="file-selector" type="file" accept=".xml,.html,.htm,text/xml,text/plain,text/html" @change="readFile" />
</div>
<InsertTemplateComponent stylized-name="HTML" @update:defaultData="setExample"></InsertTemplateComponent>
<button class="tool-button" @click="clear()">Clear</button>
<HtmlButtonFormatterComponent @update:result="format" @update:error="setErrorOccurred" :code="data" format-type="Minimize" />
<HtmlButtonFormatterComponent @update:result="format" @update:error="setErrorOccurred" :code="data" format-type="Prettify" />
<HtmlButtonFormatterComponent @update:result="format" @update:error="setErrorOccurred" :code="data" format-type="HTML -> XML" />
</div>
</div>
<CodeEditorComponent :class="highlightTextField()" @update:updated-code="setTextFieldValue" :code="data" :config="{disabled:false,language:formatterLanguage.toLowerCase()}" />
</div>
</template>

View File

@@ -1,13 +1,28 @@
<script setup lang="ts">
const props = defineProps(
{
formatType: {type:String,required:true},
code: {type:String,required:true},
formatType: {
type:String,
required:true
},
code: {
type:String,
required:true
},
isError: {
type:Boolean,
required:false
},
}
)
const emit = defineEmits([
'update:result',
'update:error'
])
function chooseType(formatType: String){
if (formatType == "XML Converter"){
if (formatType == "HTML -> XML"){
return "convert";
}
return formatType.toLowerCase();
@@ -24,7 +39,7 @@ function getTypeInfo(){
function createBody(){
return JSON.stringify({
"data": props.code,
"process": getTypeInfo(),
"processorData": getTypeInfo(),
"processor": "libxml",
"version": "1.0"
});
@@ -32,19 +47,16 @@ function createBody(){
const fetchLink = document.location.protocol + "//" + document.location.hostname + "/libxml/html/" + chooseType(props.formatType);
const emit = defineEmits([
'update:result'
])
function processResponse(formattedCode : any){
var result = formattedCode.result;
return result
}
function process(){
fetch(fetchLink, {body:createBody(), method: "POST"})
.then( response => response.json() )
.then( formattedCode => emit('update:result', processResponse(formattedCode) ) )
.then( formattedCode => processResponse(formattedCode) )
}
function processResponse(formattedCode : any){
emit('update:result', formattedCode )
emit("update:error", formattedCode.status == "ERR")
}
</script>

View File

@@ -5,12 +5,12 @@ const props = defineProps({
isMinimizer: {type: Boolean}
})
const emit = defineEmits(["update:result"])
const emit = defineEmits(["update:result", "update:error"])
function process() {
var request:Request = prepareRequest();
fetchRequest(request).then((data) => {
sendProcessedData(data);
sendProcessedData(data);
})
}
@@ -36,9 +36,11 @@ function prepareRequestBody():string {
async function fetchRequest(request: Request):Promise<JSON> {
var responseBody = await fetch(request)
.then(response => response.json())
.then(response => {
emit('update:error', response.status != 200)
return response.json()
})
.then((body) => body);
console.log(responseBody);
return responseBody;
}

View File

@@ -5,12 +5,15 @@ const props = defineProps({
isMinimizer: {type: Boolean}
})
const emit = defineEmits(["update:result"])
const emit = defineEmits([
'update:result',
'update:error'
])
function process() {
var request:Request = prepareRequest();
var request:Request = prepareRequest()
fetchRequest(request).then((data) => {
sendProcessedData(data);
sendProcessedData(data)
})
}
@@ -18,36 +21,39 @@ function prepareRequest():Request {
var request = new Request(prepareURL(), {
body: prepareRequestBody(),
method: "POST"
});
})
return request
}
function prepareURL(): string {
var mode = "prettify";
var mode = "prettify"
if (props.isMinimizer)
mode = "minimize";
return document.location.protocol + "//" + document.location.hostname + "/libxml/" + mode;
mode = "minimize"
return document.location.protocol + "//" + document.location.hostname + "/libxml/" + mode
}
function prepareRequestBody():string {
var requestBody = JSON.stringify({
"data": props.xml,
"process": "N/A",
"processorData": "N/A",
"processor": "libxml",
"version": "1.0"
});
return requestBody;
})
return requestBody
}
async function fetchRequest(request: Request):Promise<JSON> {
var responseBody = await fetch(request)
.then(response => response.json())
.then((body) => body);
return responseBody;
.then((body) => {
emit("update:error", body.status == "ERR")
return body
})
return responseBody
}
function sendProcessedData(data: JSON) {
emit("update:result", data);
emit("update:result", data)
}
</script>

View File

@@ -0,0 +1,18 @@
<script setup lang="ts">
import { ref } from 'vue'
const props = defineProps(
{
name: {type: String, required: true}
}
)
</script>
<template>
<h3 class="text-lg font-medium mt-2">{{ name }}</h3>
<p><slot></slot></p>
</template>

View File

@@ -0,0 +1,21 @@
<script setup lang="ts">
import { ref } from 'vue'
const props = defineProps(
{
imgPath: {type: String, required: true},
label: {type: String, required: true}
}
)
</script>
<template>
<div class="flex flex-col gap-2 w-fit h-fit shadow-sm bg-slate-200 dark:bg-slate-800 p-2 rounded-md my-2 text-center self-center">
<img id="url_section" class="rounded-md" :src="imgPath" />
<label for="url_section" class="text-sm mb-0 text-slate-600 dark:text-slate-300">{{ label }}</label>
</div>
</template>

View File

@@ -0,0 +1,38 @@
<script setup lang="ts">
import { ref } from 'vue';
// const props = defineProps({
// version: {
// type: String,
// required: true
// },
// toolType: {
// type: String,
// required: true
// }
// })
const emit = defineEmits([
"update:visible"
])
const areTooltipsHidden = ref(true)
function toggleTooltips() {
areTooltipsHidden.value = !areTooltipsHidden.value;
emit("update:visible", !areTooltipsHidden.value)
}
</script>
<template>
<div :class="areTooltipsHidden ? 'w-fit' : 'w-5/12'" class="hidden xl:flex items-stretch p-2 flex-row rounded-xl shadow-lg bg-gradient-to-r from-blue-400 to-blue-300 dark:from-sky-600 dark:to-sky-800 ">
<button :class="{'mr-2' : !areTooltipsHidden }" class="text-xl w-6 dark:text-slate-100" @click="toggleTooltips()">
T<br/>o<br/>o<br/>l<br/>t<br/>i<br/>p<br/>s
</button>
<div id="content" :class="{'hidden' : areTooltipsHidden}" class="w-full flex flex-col gap-4 p-2 overflow-auto rounded-xl dark:text-white bg-indigo-50 dark:bg-gray-700" >
<slot></slot>
</div>
</div>
</template>

View File

@@ -0,0 +1,71 @@
<script setup lang="ts">
import ImgMan from './ImgMan.vue';
import ElementDescription from './ElementDescription.vue';
import urlSectionImg from '@assets/man/rest-mock/URL_section.png';
import statusSectionImg from '@assets/man/rest-mock/Status_section.png';
import bodySectionImg from '@assets/man/rest-mock/Body_section.png';
import headerSectionImg from '@assets/man/rest-mock/Header_section.png';
</script>
<template>
<div class="flex flex-col dark:text-slate-100 w-full h-full text-justify overflow-auto px-2">
<h2 class="text-2xl font-bold mt-4 mb-2">Description</h2>
<p><span class="font-medium">REST Mock</span> is a tool allowing to create temporary REST endpoint called REST Mock, that allows to test REST clients.</p>
<br>
<p>Its main functions are:</p>
<ul class="list-disc ml-5">
<li>Generating random URL for each user, one per user, with persistence for 24h.</li>
<li>Customizable HTTP response status code</li>
<li>Customizable response body and its content type</li>
<li>Customizable response headers</li>
<li>History of connections to generated endpoint with ability to look into request method, headers and body</li>
</ul>
<h2 class="text-2xl font-bold mt-4 mb-2">GUI elements</h2>
<p>This section describe how certain elements of the application work:</p>
<ElementDescription name="URL field">This field contains autogenerated URL for your REST Mock. All links are removed every 24h.</ElementDescription>
<ElementDescription name="'Save' button">Applies every change made on this page and saves it between sessions.</ElementDescription>
<ElementDescription name="Response Content Type field">Its just convenient way to set "Content-Type" header in the response.</ElementDescription>
<ElementDescription name="Response HTTP Status field">This field sets HTTP status that will be sent to client. Any valid HTTP status can be used, by default it's 200 OK.</ElementDescription>
<ElementDescription name="Response Body field">Here you can set response body. This is sophisticated text editor with syntax-highlighting based on detected language. It works both with JSON and XML data.</ElementDescription>
<ElementDescription name="Response Headers section">This section contains three default and unremovable headers ("Connection", "Date", "Keep-Alive") as well as empty field used to adding custom header. Adding header with empty value is possible, but every header has to have a name. When adding new header is possible, the "Add" button becomes active. New header is added after "Add" button is clicked.</ElementDescription>
<ElementDescription name="History">This section allows to look into history of requests sent to current REST Mock. Entries are sorted by descending by date (newer are first). If request has body, "Show body" button appears in its entry. Also there is option to look into every request's headers by clicking "Show Headers" button. For now, History doesn't refresh automatically. To refresh it, click small refresh button on the right-hand side.</ElementDescription>
<h2 class="text-2xl font-bold mt-4 mb-2">Example</h2>
<p>Let's say we want to create temporary endpoint that returns code 200 with body:</p>
<div class="w-fit p-2 my-2 bg-slate-200 dark:bg-slate-800 rounded-md self-center"><pre>{
"status": "completed",
"warnings": "none"
}</pre></div>
<p>Additionally we want to set some headers:</p>
<div class="w-fit p-2 my-2 bg-slate-200 dark:bg-slate-800 rounded-md self-center"><pre> Name Value
operation addition
priority urgent
</pre></div>
<p>In this example we will focus on the left-hand side panel first as it contains most of the settings. On the top you see autogenerated URL link to your REST Mock service and the "Save" button that saves every setting on this page.</p>
<ImgMan :imgPath="urlSectionImg" label="Screenshot of Rest Mock URL bar and Save button"></ImgMan>
<p>Next, down from REST Mock URL are two text fields. One for content type of a response and second for the HTTP status of a response. </p>
<ImgMan :imgPath="statusSectionImg" label='Screenshot of "Response Content Type" and "Response HTTP Status"'></ImgMan>
<p>These two fields are first things that we will set in this example. Out content type is JSON, so we will put "application/json" in "Response Content Type" field. The "Response HTTP Status" field we'll leave
unchanged for now.</p><br/>
<p>Next element of this tool is big "Response Body" text field. Here you can put data that you want your REST Mock to respond with. In this example we will put JSON from few lines above.</p>
<ImgMan :imgPath="bodySectionImg" label='Screenshot of Response Body field filled with example JSON'></ImgMan>
<p>Last thing that we have to set are headers. Those we can set in Headers section.</p>
<ImgMan :imgPath="headerSectionImg" label='Screenshot of Headers Section with added custom headers.'></ImgMan>
</div>
</template>
<style scoped></style>

View File

@@ -55,6 +55,7 @@ function addNewHeader(name : string, value : string){
<template>
<div class="flex flex-col gap-4">
<label>Response Headers</label>
<div class="flex flex-row gap-4">
<div class="w-full">Header name</div>
<div class="w-full">Header value</div>

View File

@@ -10,14 +10,14 @@ const props = defineProps(
</script>
<template>
<div class="w-full text-center text-white mt-2 flex flex-col gap-4 ">
<div class="w-full h-2/3 text-center dark:text-white mt-2 flex flex-col gap-4 overflow-auto">
<div class="flex flex-row gap-4">
<div class="w-full font-bold">Name</div>
<div class="w-full font-bold">Value</div>
</div >
<div class="flex flex-row gap-4" v-for="(value,name) in JSON.parse(data)" :key="name">
<div class="w-full overflow-hidden">{{ name }}</div>
<div class="w-full overflow-hidden">{{ value }}</div>
<div class="w-1/2 break-words">{{ name }}</div>
<div class="w-1/2 break-words">{{ value }}</div>
</div>
</div>
</template>

View File

@@ -34,8 +34,9 @@ function showHeaders(headers: object, index: number){
<template>
<div class="w-full xl:w-2/5 flex flex-none flex-col gap-y-4">
<HistoryRecords class="xl:h-1/3 overflow-y-scroll" @click:show-headers="showHeaders" @click:show-body="showBody"></HistoryRecords>
<div class="flex flex-1 flex-col xl:w-3/12 justify-items-stretch gap-y-4">
<label class="dark:text-white text-center"><span class="font-bold">Attention! </span>History doesn't refresh automatically! Use refresh button (⟳) on the right!</label>
<HistoryRecords class="xl:h-1/3 overflow-y-auto" @click:show-headers="showHeaders" @click:show-body="showBody"></HistoryRecords>
<BodyDetailComponent :content-type="currentContentType" :data="currentShownData" v-if="shownDetail == 'body' "></BodyDetailComponent>
<HeadersDetailComponent :data="currentShownData" v-if="shownDetail == 'headers' "></HeadersDetailComponent>
</div>

View File

@@ -45,12 +45,12 @@ function refreshHistory(){
</script>
<template>
<div>
<table class="text-white h-28 w-full text-center">
<div class="h-28 text-center text-grey-900 dark:text-white">
<table class="w-full">
<tr>
<th>Time</th>
<th>HTTP Method</th>
<th>HTTP Headers</th>
<th>Request <br>HTTP Method</th>
<th>Request Headers</th>
<th>Request Body</th>
<th class="text-2xl"><button @click="refreshHistory()"></button></th>
</tr>
@@ -60,7 +60,7 @@ function refreshHistory(){
<td> <button @click="showHeaders(item.headers, index)" class="underline">Show Headers</button> </td>
<td>
<button v-if="item.requestBody.length != 0" @click="showBody(item.requestBody, index, item.headers['content-type'])" class="underline">Show Body</button>
<span v-else>Empty Body</span>
<span v-else>Empty</span>
</td>
</tr>
</table>

View File

@@ -44,31 +44,30 @@ function showUpdatedCode(newCode : string){
</script>
<template>
<div class="flex flex-col flex-none w-full xl:w-3/5 text-center dark:text-white gap-6 p-1">
<div class="flex flex-col flex-none w-full xl:w-3/5 text-center dark:text-white gap-3 p-1">
<div class="flex flex-col md:flex-row gap-4 items-center md:justify-stretch md:items-end">
<div class="flex flex-col w-full">
<label for="link">Link</label><br/>
<label for="link">REST Service URL</label>
<div class="p-2 w-full border-slate-400 border-2 rounded-lg">
<a class="underline" :href="mockMessageLink">{{ mockMessageLink }}</a>
</div>
</div>
<SaveComponent v-bind:message-data="messageData"></SaveComponent>
</div>
<div class="flex flex-col md:flex-row w-full gap-4">
<div class="w-full">
<label for="contentType">Content Type</label><br/>
<label for="contentType">Response Content Type</label><br/>
<input class="text-field" id="contentType" type="text" v-model="messageData.contentType"/>
</div>
<div class="w-full">
<label for="httpStatus">HttpStatus</label><br/>
<label for="httpStatus">Response HTTP Status</label><br/>
<input class="text-field" id="httpStatus" type="text" v-model="messageData.httpStatus"/>
</div>
</div>
<div class="flex text-left flex-col overflow-scroll h-3/4">
<label for="messageBody text-center">Body</label>
<div class="flex text-left flex-col overflow-auto gap-2 h-3/4">
<label class="text-center" for="messageBody text-center">Response Body</label>
<CodeEditorComponent
@update:updated-code="showUpdatedCode"
v-model="messageData.messageBody"

View File

@@ -15,7 +15,7 @@ const visible = ref('hidden');
const fetchLink = window.location.protocol + "//" + window.location.hostname + "/mock/api/mock";
function prepareAndSendData(){
if (props.messageData != null|| props.messageData != undefined ){
if (props.messageData != null || props.messageData != undefined ){
fetch(fetchLink, { method: "put", body:JSON.stringify(props.messageData), headers: { "Content-Type" : "application/json" }})
.then( response => response.text() )
.then( data => {message.value = data} )

View File

@@ -29,8 +29,8 @@ onMounted( () => {
<a href="https://release11.com/">
<img :src="logoR11" class="w-72 h-16 p-2 pt-0"/>
</a>
<div class="flex basis-full flex-col font-medium items-center">
<sidebar-menu-element-component category-name="XML">
<div class="flex basis-full flex-col font-normal items-center">
<sidebar-menu-element-component category-name="Parser">
<SidebarToolLinkComponent path-to="/xml/xpath" element-content="XPath" />
<SidebarToolLinkComponent path-to="/xml/xquery" element-content="XQuery" />
<SidebarToolLinkComponent path-to="/xml/xsd" element-content="XSD" />

View File

@@ -18,10 +18,10 @@ const props = defineProps(
<template>
<div class="w-full mb-4 p-2 rounded-xl shadow-lg bg-gradient-to-r from-blue-400 to-blue-300 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">
<button @click="switchHiddenElement()" type="button" :class="[isActive ? 'rounded-lg' : 'rounded-lg']" class="w-full p-1 text-lg font-normal 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>
<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']">
<div class="flex flex-col w-full mt-2 py-2 bg-indigo-50 dark:bg-slate-800 rounded-xl font-light overflow-hidden" :class="[isActive ? 'active' : 'hidden']">
<slot></slot>
</div>
</div>

View File

@@ -17,6 +17,6 @@ const props = defineProps(
<style>
.router-link-active {
font-weight: 500;
font-weight: 600;
}
</style>

View File

@@ -1,10 +1,11 @@
<script setup lang="ts">
import InsertTemplateComponent from '@components/common/InsertTemplateComponent.vue';
import InsertTemplateComponent from '@components/common/InsertTemplateComponent.vue'
import XMLButtonFormatterComponent from '@components/formatter/XMLButtonFormatterComponent.vue'
import { ref } from 'vue';
import CodeEditor from '../CodeEditorComponent.vue';
import { ref } from 'vue'
import CodeEditor from '../CodeEditorComponent.vue'
const data = ref('')
const inputFile = ref()
const props = defineProps(
{
@@ -15,7 +16,6 @@ const props = defineProps(
const emit = defineEmits(['update'])
function sendValue() {
console.log("input works")
emit('update', data.value)
}
@@ -25,27 +25,44 @@ function sendNewValue(newValue : string) {
}
function updateData(newData: string) {
data.value = newData;
sendValue();
data.value = newData
inputFile.value.value = ''
sendValue()
}
function clear() {
updateData('');
updateData('')
}
function canBeFormatted() {
return props.stylizedName.toLowerCase() == 'xml' ||
props.stylizedName.toLowerCase() == 'xsd' ||
props.stylizedName.toLowerCase() == 'xslt';
props.stylizedName.toLowerCase() == 'xslt'
}
function readFile(file : any) {
const reader = new FileReader()
reader.onloadend = () => {
var result = reader.result?.toString()
if (typeof result == "string")
sendNewValue(result)
}
reader.readAsText(file.target.files[0])
}
</script>
<template>
<div class="flex flex-col w-full h-1/2 lg:h-1/2 flex-none pr-4 pb-2">
<div class="flex flex-col w-full h-1/2 lg:h-1/2 flex-none xl:pr-2 2xl:pr-4 pb-2">
<div class="flex place-content-between w-full items-center">
<span class="dark:text-white">{{ stylizedName }}</span>
<div class="flex space-x-2 pb-2">
<span class="dark:text-white mr-2">{{ stylizedName }}</span>
<div class="flex space-x-2 pb-2 overflow-x-auto">
<div class="flex items-stretch w-64">
<input id="fileLoader" ref="inputFile" class="file-selector" type="file" accept=".xml,.xql,.xquery,.xslt,text/xml,text/plain" @change="readFile" />
</div>
<InsertTemplateComponent :stylized-name="props.stylizedName" @update:default-data="(data: string) => updateData(data)"></InsertTemplateComponent>
<XMLButtonFormatterComponent v-if="canBeFormatted()" :xml="data" @update:result="(data:any) => updateData(data.result)"></XMLButtonFormatterComponent>
<button class="tool-button" @click="clear">Clear</button>

View File

@@ -1,22 +0,0 @@
<script setup lang="ts">
import InsertTemplateComponent from '@components/common/InsertTemplateComponent.vue'
const props = defineProps(
{
prettyName: {type: String, required: true}
}
)
const emit = defineEmits(['update:defaultData'])
function setDefault(data: string) {
const emitName = "update:defaultData";
emit(emitName, data)
}
</script>
<template>
</template>

View File

@@ -23,6 +23,9 @@ var versionsForCurrentEngine = ref([""]);
const engine = ref('');
const version = ref('');
const errorOccurred = ref(false);
const successOccurred = ref(false);
onMounted(() => {
changeAvailableEngines();
@@ -47,6 +50,7 @@ function changeAvailableVersions() {
changeAvailableVersionsOfXSLT();
else if (props.tool == "xsd")
versionsForCurrentEngine.value = ["N/A"];
else if (props.tool == "xpath")
changeAvailableVersionsOfXPath();
@@ -72,7 +76,7 @@ function selectDefaultEngine() {
}
function selectDefaultVersion() {
const lastVersion = versionsForCurrentEngine.value.length - 1
const lastVersion = versionsForCurrentEngine.value.length - 1;
version.value = versionsForCurrentEngine.value[lastVersion];
emitVersionChange();
}
@@ -111,40 +115,58 @@ function prepareRequestBody():string {
async function fetchRequest(request: Request):Promise<JSON> {
var responseBody = await fetch(request)
.then(response => response.json())
.then((body) => body);
return responseBody;
.then((body) => body)
return responseBody
}
function updateOutputField(data: any) {
result.value = data.result;
result.value = data.result
errorOccurred.value = data.status != "OK"
successOccurred.value = data.status == "OK"
}
function clear() {
result.value = "";
result.value = ""
errorOccurred.value = false
successOccurred.value = false
}
function emitVersionChange() {
emit("update", version.value);
}
function isVersionSelectionAvailable() {
return !(props.tool == "xsd");
}
function highlightField() {
if (errorOccurred.value) {
return "text-field-error";
}
if (successOccurred.value) {
return "text-field-success";
}
return "";
}
</script>
<template>
<div class="flex flex-col flex-none w-full lg:w-1/2 h-1/3 lg:h-full items-center pb-2 pr-2">
<div class="flex flex-col flex-none w-full 2xl:w-1/2 h-1/3 2xl:h-full items-center pb-2 xl:pr-2">
<div class="flex place-content-between w-full items-center pb-2">
<span class="dark:text-white">Result:</span>
<div class="flex space-x-2">
<div class="flex space-x-2 overflow-x-auto">
<select v-model="engine" name="engine" @change="changeAvailableVersions()" class="px-3 rounded-full border border-slate-400 bg-white dark:text-slate-100 dark:bg-gray-600">
<option v-for="engine in enginesForCurrentTool" :value="engine">{{ engine }}</option>
</select>
<select v-model="version" name="version" @change="emitVersionChange()" class="px-3 rounded-full border border-slate-400 bg-white dark:text-slate-100 dark:bg-gray-600">
<select v-model="version" v-if="isVersionSelectionAvailable()" name="version" @change="emitVersionChange()" class="px-3 rounded-full border border-slate-400 bg-white dark:text-slate-100 dark:bg-gray-600">
<option v-for="version in versionsForCurrentEngine" :value="version">{{ version }}</option>
</select>
<button class="tool-button" @click="clear">Clear</button>
<button class="tool-button" @click="process">Process</button>
</div>
</div>
<div class="overflow-scroll h-full w-full">
<div class="overflow-auto h-full w-full rounded-2xl" :class="highlightField()">
<CodeEditor :code="result" :config="{disabled:true,language:tool}"></CodeEditor>
</div>

View File

@@ -13,7 +13,7 @@ function toggleTooltips() {
</script>
<template>
<div class="flex p-2 flex-col rounded-xl shadow-lg bg-gradient-to-r from-zinc-400 to-slate-400 dark:from-slate-600 dark:to-slate-700">
<div class="flex p-2 flex-col rounded-xl shadow-lg bg-gradient-to-r from-gray-300 to-slate-300 dark:from-slate-500 dark:to-slate-600">
<button :class="{ 'mb-2' : !isCategoryHidden }" class="dark:text-slate-100 hover:font-bold" @click="toggleTooltips()">{{ props.name }}</button>
<div id="content" :class="{'hidden' : isCategoryHidden}" class="flex flex-col gap-4 w-full h-fit p-2 rounded-xl dark:text-white bg-indigo-50 dark:bg-slate-800" >
<slot></slot>

View File

@@ -58,11 +58,11 @@ function toggleTooltips() {
</script>
<template>
<div :class="areTooltipsHidden ? 'w-fit' : 'w-4/12'" class="hidden 2xl:flex shrink-0 items-stretch p-2 flex-row rounded-xl shadow-lg bg-gradient-to-r from-blue-400 to-blue-300 dark:from-sky-600 dark:to-sky-800 ">
<div :class="areTooltipsHidden ? 'w-fit' : 'w-[26rem]'" class="hidden xl:flex shrink-0 items-stretch p-2 flex-row rounded-xl shadow-lg bg-gradient-to-r from-blue-400 to-blue-300 dark:from-sky-600 dark:to-sky-800 ">
<button :class="{'mr-2' : !areTooltipsHidden }" class="text-xl w-6 dark:text-slate-100" @click="toggleTooltips()">
T<br/>o<br/>o<br/>l<br/>t<br/>i<br/>p<br/>s
</button>
<div id="content" :class="{'hidden' : areTooltipsHidden}" class="w-full flex flex-col gap-4 p-2 overflow-scroll rounded-xl dark:text-white bg-indigo-50 dark:bg-slate-800" >
<div id="content" :class="{'hidden' : areTooltipsHidden}" class="w-full flex flex-col gap-4 p-2 overflow-auto rounded-xl dark:text-white bg-indigo-50 dark:bg-gray-700" >
<TooltipDiffsComponent :tool-name="toolType" :tool-version="props.version"></TooltipDiffsComponent>
<div class="w-full h-2"> </div>
<tooltipCategoryComponent v-for="category in selectTooltip()" :key="category.name" :name="category.name">

View File

@@ -12,19 +12,19 @@ const props = defineProps({
function getDiffEntry(toolVersion : String) : string[] {
if ( props.toolName == "xpath" ){
switch(toolVersion){
case "2.0" : {
return xpathDiffs.VersionDiffs[0].diffs
case "2.0" : {
return xpathDiffs.VersionDiffs[0].diffs
}
case "3.0" : {
return xpathDiffs.VersionDiffs[1].diffs
}
case "3.1" : {
return xpathDiffs.VersionDiffs[2].diffs
}
default: {
return xpathDiffs.VersionDiffs[2].diffs
}
}
case "3.0" : {
return xpathDiffs.VersionDiffs[1].diffs
}
case "3.1" : {
return xpathDiffs.VersionDiffs[2].diffs
}
default: {
return xpathDiffs.VersionDiffs[2].diffs
}
}
} else if (props.toolName == "xslt") {
return ["XSLT 2.0"].concat(xsltDiffs.VersionDiffs[0].diffs).concat(["XSLT 3.0"]).concat(xsltDiffs.VersionDiffs[1].diffs) ;
} else{
@@ -56,7 +56,7 @@ function getInfo(num : number ){
</span>
</TooltipCategoryComponent>
<TooltipCategoryComponent v-if="toolVersion !== '1.0'" :name="getInfo(1).category">
<TooltipCategoryComponent v-if="toolVersion !== '1.0'" :name="getInfo(1).category + ' ' + toolVersion + '?'">
<span v-for=" diff in getDiffEntry(toolVersion)" v-bind:key="diff" class=" text-justify" >
<div class="w-full h-4 text-center" v-if="diff.includes('XSLT')">
------------ {{ diff }} ------------

Binary file not shown.

Binary file not shown.

View File

@@ -15,6 +15,8 @@ const xqueryTool = import("@views/XQueryView.vue")
const base64Encoder = import("@views/Base64EncoderView.vue")
const urlEncoder = import("@views/UrlEncoderView.vue")
const restMockMan = import("@views/man/RestMockManView.vue")
const routes = [
{
path: '/',
@@ -70,6 +72,11 @@ const routes = [
path: '/encoder/url',
name: 'urlEncoder',
component: () => urlEncoder
},
{
path: '/man/rest-mock',
name: 'RestMockManView',
component: () => restMockMan
}
]

View File

@@ -2,14 +2,36 @@
@tailwind components;
@tailwind utilities;
@font-face {
font-family: "Raleway";
src: url("fonts/Raleway-Variable.ttf");
}
@font-face {
font-family: "Sono";
src: url("fonts/Sono-Variable.ttf");
}
.inactive-button {
@apply py-2 px-4 h-fit text-slate-400 border border-slate-400 rounded-full
}
.tool-button {
@apply hover:brightness-110 py-2 px-4 h-fit rounded-full bg-gradient-to-r from-blue-400 to-sky-300 dark:text-white dark:from-sky-600 dark:to-sky-800 hover:bg-blue-400
@apply hover:brightness-110 py-2 px-3 h-fit min-w-fit rounded-full bg-gradient-to-r from-blue-400 to-sky-300 dark:text-white dark:from-sky-600 dark:to-sky-800 hover:bg-blue-400
}
.text-field {
@apply w-full font-mono dark:text-slate-100 bg-slate-50 dark:bg-gray-600 border border-slate-400 p-2 rounded-lg
}
.file-selector {
@apply block file:border-none file:font-sans file:text-base file:hover:brightness-110 file:py-2 file:px-3 file:h-full file:w-fit file:rounded-full file:bg-gradient-to-r file:from-blue-400 file:to-sky-300 file:dark:text-white file:dark:from-sky-600 file:dark:to-sky-800 file:hover:bg-blue-400 w-fit rounded-full text-sm text-gray-900 border border-gray-300 cursor-pointer bg-gray-50 dark:text-gray-400 focus:outline-none dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400
}
.text-field-error {
@apply shadow-[0px_0px_10px_0px_rgba(255,0,0,1)];
}
.text-field-success {
@apply shadow-[0px_0px_10px_0px_rgba(52,211,153,1)];
}

View File

@@ -1,62 +1,71 @@
<script setup lang="ts">
import CodeEditorComponent from '@/components/CodeEditorComponent.vue';
import CodeEditorComponent from '@/components/CodeEditorComponent.vue'
import EncoderButton from '@/components/encoder/EncoderButtonComponent.vue'
import { ref } from 'vue';
import { ref } from 'vue'
const data : any = ref("")
const imageData = ref("")
const DoshowImage = ref(false)
const inputImage = ref();
const inputImage = ref()
function setTextFieldValue(newData: string) {
data.value = newData.toString()
DoshowImage.value = false;
DoshowImage.value = false
}
function showImage(newImage : string){
imageData.value = "data:image/jpeg;base64,"+newImage
DoshowImage.value = true;
DoshowImage.value = true
}
function convertImageToBase64(file : any){
console.log(inputImage)
const reader = new FileReader()
reader.onloadend = () => (console.log(data.value = reader.result?.toString().split(',')[1]))
reader.onloadend = () => {
data.value = reader.result?.toString().split(',')[1]
showImage(data.value)
}
reader.readAsDataURL(file.target.files[0])
}
function clear(){
data.value = ""
imageData.value = ""
DoshowImage.value = false;
DoshowImage.value = false
inputImage.value.value = null
}
</script>
<template>
<div id="layoutFull" class="w-full h-full flex">
<div id="layoutLeft" class="flex flex-col w-1/2 h-full gap-4">
<div class="w-4/5 flex flex-row-reverse gap-2 mt-12 ml-6">
<EncoderButton @update:result="setTextFieldValue" :code="data" encode-type="Base64"></EncoderButton>
<EncoderButton @update:result="setTextFieldValue" :code="data" encode-type="Text"></EncoderButton>
<EncoderButton @image:show="showImage" :code="data" encode-type="Image"></EncoderButton>
<button class="tool-button" @click="clear()">Clear</button>
<div id="layoutFull" class="w-full h-full flex flex-col xl:flex-row gap-4">
<div id="layoutLeft" class="flex flex-col w-full xl:w-1/2 h-1/3 xl:h-full gap-4">
<div class="w-full flex flex-row place-content-between items-center">
<label class="dark:text-white text-center">Base64 Encoder</label>
<div class="flex flex-row items-center gap-2 overflow-x-auto">
<button class="tool-button" @click="clear()">Clear</button>
<EncoderButton @image:show="showImage" :code="data" operation-type="Show Image"></EncoderButton>
<div class="w-2"></div>
<EncoderButton @update:result="setTextFieldValue" :code="data" operation-type="Encode"></EncoderButton>
<EncoderButton @update:result="setTextFieldValue" :code="data" operation-type="Decode"></EncoderButton>
</div>
</div>
<div id="codeEditor" class="w-4/5 h-1/3 ml-6 flex flex-col">
<label class="dark:text-white text-center w-full">Base64</label>
<div id="codeEditor" class="w-full h-full xl:h-1/3 flex flex-col">
<CodeEditorComponent @update:updated-code="setTextFieldValue" :config="{language:'base64'}" :code="data"></CodeEditorComponent>
</div>
<div class="w-4/5 flex items-center flex-col ml-6" id="imageImporter">
<label class="block mb-2 text-sm font-medium text-gray-900 dark:text-white" for="file_input">Upload file</label>
<input id="imageLoader" ref="inputImage" class="block file:bg-inherit file:shadow-inherit dark:file:text-white file:border-inherit w-full text-sm text-gray-900 border border-gray-300 rounded-lg cursor-pointer bg-gray-50 dark:text-gray-400 focus:outline-none dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400" type="file" @change="convertImageToBase64" />
<div class="flex flex-row justify-center w-full">
<div class="flex flex-col items-center w-fit" id="imageImporter">
<label class="block mb-2 text-sm font-medium text-gray-900 dark:text-white" for="file_input">Upload image</label>
<input id="imageLoader" ref="inputImage" class="file-selector" accept=".gif, .jpg, .jpeg, .png, .webm, image/gif, image/jpeg, image/png, image/webm" type="file" @change="convertImageToBase64" />
</div>
</div>
</div>
<div id="separator" class="bg-black h-full w-1" ></div>
<div id="layoutRight" class=" ml-6 w-2/5">
<div v-on="DoshowImage">
<div id="layoutRight" class="w-full xl:w-1/2 min-h-[66%] xl:h-full">
<div class="border-2 rounded-lg border-gray-300 dark:border-gray-600 min-h-[50%]" v-on="DoshowImage">
<img :src="imageData"/>
</div>

View File

@@ -1,34 +1,8 @@
<script setup lang="ts">
import InsertTemplateComponent from '@components/common/InsertTemplateComponent.vue';
import CodeEditorComponent from '@/components/CodeEditorComponent.vue';
import { ref } from 'vue';
import HtmlButtonFormatterComponent from '@/components/formatter/HtmlButtonFormatterComponent.vue';
const html = ref('');
function clear() {
html.value = '';
}
function setTextFieldValue(data: string) {
html.value = data.toString()
}
import FormatterComponent from '@/components/formatter/FormatterComponent.vue';
</script>
<template>
<div id="layout" class="flex flex-col w-full h-full gap-4">
<div id="toolbar" class="flex flex-col gap-4 items-center lg:flex-row place-content-between">
<span class="dark:text-slate-100">HTML Formatter</span>
<div class="flex flex-wrap gap-2 justify-center">
<InsertTemplateComponent stylized-name="HTML" @update:defaultData="setTextFieldValue"></InsertTemplateComponent>
<button class="tool-button" @click="clear()">Clear</button>
<HtmlButtonFormatterComponent @update:result="setTextFieldValue" :code="html" format-type="Minimize" />
<HtmlButtonFormatterComponent @update:result="setTextFieldValue" :code="html" format-type="Prettify" />
<HtmlButtonFormatterComponent @update:result="setTextFieldValue" :code="html" format-type="XML Converter" />
</div>
</div>
<CodeEditorComponent @update:updated-code="setTextFieldValue" :code="html" :config="{disabled:false,language:'html'}" />
</div>
<FormatterComponent formatter-language="HTML"></FormatterComponent>
</template>

View File

@@ -1,37 +1,8 @@
<script setup lang="ts">
import CodeEditorComponent from '@/components/CodeEditorComponent.vue';
import JsonButtonFormatterComponent from '@/components/formatter/JsonButtonFormatterComponent.vue';
import InsertTemplateComponent from '@components/common/InsertTemplateComponent.vue';
import { ref } from 'vue';
const json = ref('');
function setTextFieldValue(data: string) {
json.value = data
}
function format(formattedXml: any) {
json.value = formattedXml.data;
}
function clear() {
json.value = '';
}
import FormatterComponent from '@/components/formatter/FormatterComponent.vue';
</script>
<template>
<div id="layout" class="flex flex-col w-full h-full gap-4">
<div id="toolbar" class= "flex flex-col gap-4 items-center lg:flex-row place-content-between">
<span class="dark:text-slate-100">JSON Formatter</span>
<div class="flex flex-wrap gap-2 justify-center">
<InsertTemplateComponent stylized-name="JSON" @update:defaultData="(data: string) => setTextFieldValue(data)"></InsertTemplateComponent>
<button class="tool-button" @click="clear()">Clear</button>
<JsonButtonFormatterComponent isMinimizer :json="json" @update:result="(data: any) => format(data)"></JsonButtonFormatterComponent>
<JsonButtonFormatterComponent :json="json" @update:result="(data: any) => format(data)"></JsonButtonFormatterComponent>
</div>
</div>
<CodeEditorComponent @update:updated-code="setTextFieldValue" :code="json" :config="{disabled:false,language:'json'}" />
</div>
<FormatterComponent formatter-language="JSON"></FormatterComponent>
</template>

View File

@@ -1,14 +1,29 @@
<script setup lang="ts">
import RestMockMessageComponent from '@components/mock/RestMockMessageComponent.vue'
import HistoryComponent from '@components/mock/HistoryComponent.vue'
import ManTooltipComponent from '@/components/man/ManTooltipComponent.vue';
import RestMockManComponent from '@/components/man/RestMockManComponent.vue';
import { ref } from 'vue';
const historyVisibility = ref(true);
function setHistoryVisibility(visibility : boolean) {
historyVisibility.value = !visibility;
}
</script>
<template>
<div class="flex flex-col xl:flex-row gap-6 w-full overflow-y-scroll overflow-x-hidden h-full">
<div class="flex flex-col xl:flex-row gap-6 w-full overflow-y-auto overflow-x-hidden h-full">
<RestMockMessageComponent></RestMockMessageComponent>
<HistoryComponent></HistoryComponent>
<HistoryComponent :class="{'hidden': !historyVisibility}"></HistoryComponent>
<ManTooltipComponent @update:visible="setHistoryVisibility">
<div class="mt-2">
<a class="tool-button" href="/man/rest-mock">Expand</a>
</div>
<RestMockManComponent></RestMockManComponent>
</ManTooltipComponent>
</div>
</template>

View File

@@ -16,9 +16,9 @@ function updateVersion(newVersion: string) {
</script>
<template>
<div id="layout" class="flex flex-col lg:flex-row w-full h-full">
<div class="flex flex-col lg:flex-row w-full lg:w-7/12 grow overflow-hide px-2">
<div class="flex flex-col w-full lg:w-1/2 h-2/3 lg:h-full flex-none items-center">
<div id="layout" class="flex flex-row w-full h-full">
<div class="flex flex-col 2xl:flex-row w-full xl:w-7/12 grow overflow-hide xl:pr-2">
<div class="flex flex-col w-full 2xl:w-1/2 h-2/3 2xl:h-full flex-none items-center">
<xmlInputFieldComponent stylized-name="XML" :data="xml" @update="(data) => {xml = data}"></xmlInputFieldComponent>
<xmlInputFieldComponent stylized-name="XPath" :data="query" @update="(data) => {query = data}"></xmlInputFieldComponent>
</div>

View File

@@ -10,8 +10,8 @@ const query = ref('');
</script>
<template>
<div id="layout" class="flex flex-col lg:flex-row w-full h-full">
<div class="flex flex-col w-full lg:w-1/2 h-2/3 lg:h-full flex-none items-center">
<div id="layout" class="flex flex-col 2xl:flex-row w-full h-full">
<div class="flex flex-col w-full 2xl:w-1/2 h-2/3 2xl:h-full flex-none items-center">
<xmlInputFieldComponent stylized-name="XML" @update="(data) => {xml = data}"></xmlInputFieldComponent>
<xmlInputFieldComponent stylized-name="XQuery" @update="(data) => {query = data}"></xmlInputFieldComponent>
</div>

View File

@@ -10,8 +10,8 @@ const query = ref('');
</script>
<template>
<div id="layout" class="flex flex-col lg:flex-row w-full h-full">
<div class="flex flex-col w-full lg:w-1/2 h-2/3 lg:h-full flex-none items-center">
<div id="layout" class="flex flex-col 2xl:flex-row w-full h-full">
<div class="flex flex-col w-full 2xl:w-1/2 h-2/3 2xl:h-full flex-none items-center">
<xmlInputFieldComponent stylized-name="XML" @update="(data) => {xml = data}"></xmlInputFieldComponent>
<xmlInputFieldComponent stylized-name="XSD" @update="(data) => {query = data}"></xmlInputFieldComponent>
</div>

View File

@@ -15,13 +15,13 @@ function updateVersion(newVersion: string) {
</script>
<template>
<div id="layout" class="flex flex-col lg:flex-row w-full h-full">
<div class="flex flex-col lg:flex-row w-full lg:w-7/12 grow overflow-hide px-2">
<div class="flex flex-col w-full lg:w-1/2 h-2/3 lg:h-full flex-none items-center">
<xmlInputFieldComponent stylized-name="XML" @update="(data) => {xml = data}"></xmlInputFieldComponent>
<xmlInputFieldComponent stylized-name="XSLT" @update="(data) => {query = data}"></xmlInputFieldComponent>
</div>
<xmlOutputFieldComponent tool="xslt" :xml="xml" :query="query" @update="(version) => updateVersion(version)"></xmlOutputFieldComponent>
<div id="layout" class="flex flex-row w-full h-full">
<div class="flex flex-col 2xl:flex-row w-full xl:w-7/12 grow overflow-hide pr-2">
<div class="flex flex-col w-full 2xl:w-1/2 h-2/3 2xl:h-full flex-none items-center">
<xmlInputFieldComponent stylized-name="XML" :data="xml" @update="(data) => {xml = data}"></xmlInputFieldComponent>
<xmlInputFieldComponent stylized-name="XSLT" :data="query" @update="(data) => {query = data}"></xmlInputFieldComponent>
</div>
<xmlOutputFieldComponent tool="xslt" :xml="xml" :query="query" @update="(version) => updateVersion(version)"></xmlOutputFieldComponent>
</div>
<TooltipComponent tool-type="xslt" :version="version"></TooltipComponent>
</div>

View File

@@ -1,37 +1,8 @@
<script setup lang="ts">
import XMLButtonFormatterComponent from '@/components/formatter/XMLButtonFormatterComponent.vue';
import InsertTemplateComponent from '@components/common/InsertTemplateComponent.vue';
import CodeEditorComponent from '@/components/CodeEditorComponent.vue';
import { ref } from 'vue';
const xml = ref('');
function setTextFieldValue(data: string) {
xml.value = data
}
function format(formattedXml: any) {
xml.value = formattedXml.result;
}
function clear() {
xml.value = '';
}
import FormatterComponent from '@/components/formatter/FormatterComponent.vue';
</script>
<template>
<div id="layout" class="flex flex-col w-full h-full gap-4">
<div id="toolbar" class= "flex flex-col gap-4 items-center lg:flex-row place-content-between">
<span class="dark:text-slate-100">XML Formatter</span>
<div class="flex flex-wrap gap-2 justify-center">
<InsertTemplateComponent stylized-name="XML" @update:defaultData="(data: string) => setTextFieldValue(data)"></InsertTemplateComponent>
<button class="tool-button" @click="clear()">Clear</button>
<XMLButtonFormatterComponent is-minimizer :xml="xml" @update:result="(data: any) => format(data)"></XMLButtonFormatterComponent>
<XMLButtonFormatterComponent :xml="xml" @update:result="(data: any) => format(data)"></XMLButtonFormatterComponent>
</div>
</div>
<CodeEditorComponent @update:updated-code="setTextFieldValue" :code="xml" :config="{disabled:false,language:'xml'}" />
</div>
<FormatterComponent formatter-language="XML"></FormatterComponent>
</template>

View File

@@ -0,0 +1,20 @@
<script lang="ts">
import RestMockManComponent from '@man/RestMockManComponent.vue'
export default {
name:"RestMockManView",
components: {RestMockManComponent}
}
</script>
<template>
<div class="flex flex-col h-full gap-4">
<div class="flex flex-row">
<a href="/rest/mock" class="tool-button">Back to REST Mock</a>
</div>
<RestMockManComponent></RestMockManComponent>
</div>
</template>

View File

@@ -6,6 +6,10 @@ export default {
],
theme: {
extend: {},
fontFamily: {
'sans': ['Raleway'],
'mono': ["Sono"],
}
},
plugins: [],
}

View File

@@ -35,6 +35,7 @@ export default defineConfig({
'@components': fileURLToPath(new URL('./src/components', import.meta.url)),
'@views': fileURLToPath(new URL('./src/views', import.meta.url)),
'@assets': fileURLToPath(new URL('./src/assets', import.meta.url)),
'@man': fileURLToPath(new URL('./src/components/man', import.meta.url)),
}
}
})