mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2024-11-25 10:10:32 -06:00
incremental work on NBUI
This commit is contained in:
parent
50c1cd2a1d
commit
69dbd0a6ed
@ -5,11 +5,6 @@
|
||||
<v-btn to="/ui/run/" title="Run a workload">Run</v-btn>
|
||||
<v-btn to="/ui/watch/" title="Watch workload status">Watch</v-btn>
|
||||
<v-btn to="/docs/" title="Documentation">Docs</v-btn>
|
||||
<v-btn
|
||||
title="Give us your feedback!"
|
||||
href="https://github.com/nosqlbench/nosqlbench/wiki/Submitting-Feedback">
|
||||
<v-icon>mdi-lightbulb-on-outline</v-icon>
|
||||
</v-btn>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
@ -1,11 +1,24 @@
|
||||
<template>
|
||||
<v-app-bar app fluid>
|
||||
<!-- <v-app-bar app dark fluid dense flat>-->
|
||||
<v-toolbar-title><slot></slot></v-toolbar-title>
|
||||
<v-toolbar-title>
|
||||
<slot></slot>
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-toolbar-items>
|
||||
<app-selector></app-selector>
|
||||
<workspace-selector></workspace-selector>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-btn icon large
|
||||
title="Give us your feedback!"
|
||||
href="https://github.com/nosqlbench/nosqlbench/wiki/Submitting-Feedback">
|
||||
<v-icon>mdi-lightbulb-on-outline</v-icon>
|
||||
</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
</v-toolbar-items>
|
||||
</v-app-bar>
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
<div class="markdown-body" v-html="rendered"></div>
|
||||
</template>
|
||||
|
||||
<!--previously: https://github.com/ravenq/markdown-it-vue/blob/master/src/markdown-it-vue.vue-->
|
||||
|
||||
<script>
|
||||
import "markdown-it"
|
||||
import "markdown-it-imsize"
|
||||
|
@ -9,8 +9,8 @@
|
||||
v-model="new_workspace"
|
||||
ref="new_workspace_input"
|
||||
hint="workspace name"
|
||||
@blur="commitWorkspace(new_workspace)"
|
||||
@keydown.enter="commitWorkspace(new_workspace)"
|
||||
@blur="initializeWorkspace(new_workspace)"
|
||||
@keydown.enter="initializeWorkspace(new_workspace)"
|
||||
@keydown.esc="cancelWorkspace()"
|
||||
></v-text-field>
|
||||
<!-- label="workspace"-->
|
||||
@ -77,7 +77,7 @@ export default {
|
||||
this.$refs.new_workspace_input.focus();
|
||||
});
|
||||
},
|
||||
commitWorkspace: function ({$store}) {
|
||||
initializeWorkspace: function ({$store}) {
|
||||
// console.log("commit:" + JSON.stringify(this.new_workspace));
|
||||
this.$store.dispatch("workspaces/activateWorkspace", this.new_workspace);
|
||||
this.new_workspace = "";
|
||||
|
@ -114,36 +114,27 @@ export default {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.container {
|
||||
min-height: 60vh;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
text-align: start;
|
||||
margin: 0 auto 0 15px;
|
||||
}
|
||||
<style scoped>
|
||||
/*.title {*/
|
||||
/* font-family: 'Quicksand', 'Source Sans Pro', -apple-system, BlinkMacSystemFont,*/
|
||||
/* 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;*/
|
||||
/* display: block;*/
|
||||
/* font-weight: 300;*/
|
||||
/* font-size: 100px;*/
|
||||
/* color: #35495e;*/
|
||||
/* letter-spacing: 1px;*/
|
||||
/*}*/
|
||||
|
||||
.title {
|
||||
font-family: 'Quicksand', 'Source Sans Pro', -apple-system, BlinkMacSystemFont,
|
||||
'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
display: block;
|
||||
font-weight: 300;
|
||||
font-size: 100px;
|
||||
color: #35495e;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
/*.subtitle {*/
|
||||
/* font-weight: 300;*/
|
||||
/* font-size: 42px;*/
|
||||
/* color: #526488;*/
|
||||
/* word-spacing: 5px;*/
|
||||
/* padding-bottom: 15px;*/
|
||||
/*}*/
|
||||
|
||||
.subtitle {
|
||||
font-weight: 300;
|
||||
font-size: 42px;
|
||||
color: #526488;
|
||||
word-spacing: 5px;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
.links {
|
||||
padding-top: 15px;
|
||||
}
|
||||
/*.links {*/
|
||||
/* padding-top: 15px;*/
|
||||
/*}*/
|
||||
</style>
|
||||
|
||||
|
@ -1,52 +1,44 @@
|
||||
<template>
|
||||
<v-app>
|
||||
<main-app-bar>NoSQLBench - Workload Builder</main-app-bar>
|
||||
|
||||
<v-layout>
|
||||
<main-app-bar>NoSQLBench - Workload Builder</main-app-bar>
|
||||
|
||||
<v-row>
|
||||
<v-main>
|
||||
<v-container fluid>
|
||||
<v-layout row>
|
||||
<v-flex>
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
Workload details
|
||||
</v-card-title>
|
||||
<v-col
|
||||
cols="12"
|
||||
sm="6"
|
||||
md="10"
|
||||
lg="10"
|
||||
>
|
||||
<v-text-field
|
||||
outlined
|
||||
label="Workload name"
|
||||
v-model="workloadName"
|
||||
></v-text-field>
|
||||
<v-row>
|
||||
<v-alert
|
||||
v-if="!enabled"
|
||||
>This component is not online. This is only a preview. To use this, you must be running a local instance of NoSQLBench in appserver mode.</v-alert>
|
||||
</v-row>
|
||||
|
||||
<v-textarea
|
||||
outlined
|
||||
label="Create Table Statement"
|
||||
v-model="createTableDef"
|
||||
v-on:blur="parseStatement()"
|
||||
></v-textarea>
|
||||
<v-row class="d-flex justify-center">
|
||||
<v-btn
|
||||
:disabled="buildmode==='cql'"
|
||||
title="Build CQL workload from schema"
|
||||
@click="buildmode=(buildmode==='cql' ? null : 'cql')"
|
||||
>CQL
|
||||
</v-btn>
|
||||
|
||||
</v-col>
|
||||
<v-btn
|
||||
:disabled="buildmode==='openapi'"
|
||||
title="Build OpenAPI workload from OpenAPI spec"
|
||||
@click="buildmode='openapi'"
|
||||
>OpenAPI
|
||||
</v-btn>
|
||||
</v-row>
|
||||
|
||||
<v-col cols="12">
|
||||
<v-btn :title="save_title" v-if="parseSuccess" v-on:click="saveWorkloadToWorkspace()">{{ save_button }}</v-btn>
|
||||
<v-btn :title="dl_title" v-if="parseSuccess" v-on:click="downloadWorkload()">{{ dl_button }}</v-btn>
|
||||
</v-col>
|
||||
</v-card>
|
||||
</v-flex>
|
||||
|
||||
</v-layout>
|
||||
<v-row row v-if="buildmode==='openapi'">
|
||||
<OpenApiBuilder></OpenApiBuilder>
|
||||
</v-row>
|
||||
|
||||
<v-row row v-if="buildmode==='cql'">
|
||||
<CqlBuilder></CqlBuilder>
|
||||
</v-row>
|
||||
|
||||
</v-container>
|
||||
|
||||
</v-main>
|
||||
</v-layout>
|
||||
</v-row>
|
||||
|
||||
<v-footer app>
|
||||
<span>© 2020</span>
|
||||
@ -55,222 +47,35 @@
|
||||
</v-app>
|
||||
</template>
|
||||
<script>
|
||||
import antlr4 from "antlr4";
|
||||
import {saveAs} from "file-saver";
|
||||
import yamlDumper from "js-yaml";
|
||||
import CQL3Parser from '@/antlr/CQL3Parser.js';
|
||||
import CQL3Lexer from '@/antlr/CQL3Lexer.js';
|
||||
import defaultYaml from 'assets/default.yaml';
|
||||
import basictypes from 'assets/basictypes.yaml';
|
||||
import WorkspaceSelector from "@/components/WorkspaceSelector";
|
||||
import AppSelector from "@/components/AppSelector";
|
||||
import MainAppBar from "@/components/MainAppBar";
|
||||
import CqlBuilder from "~/components/builders/CqlBuilder";
|
||||
import OpenApiBuilder from "~/components/builders/OpenApiBuilder";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MainAppBar,
|
||||
AppSelector,
|
||||
WorkspaceSelector
|
||||
WorkspaceSelector,
|
||||
CqlBuilder,
|
||||
OpenApiBuilder
|
||||
},
|
||||
data(context) {
|
||||
let data = {
|
||||
enabled: false,
|
||||
createTableDef: "",
|
||||
workloadName: "",
|
||||
parseSuccess: false,
|
||||
blob: null,
|
||||
buildmode: 'cql',
|
||||
};
|
||||
return data;
|
||||
},
|
||||
computed: {
|
||||
save_button: function () {
|
||||
return "Save to workspace '" + this.$store.getters["workspaces/getWorkspace"] + "'";
|
||||
},
|
||||
dl_button: function () {
|
||||
return "Download as " + this.filename;
|
||||
},
|
||||
dl_title: function () {
|
||||
return "Click to download the workload as '" + this.filename + "'";
|
||||
},
|
||||
filename: function () {
|
||||
return this.workloadName + ".yaml";
|
||||
},
|
||||
save_title: function () {
|
||||
return "Click to save this workload in the '" + this.workspace + "' workspace, or change the workspace in the app bar first.\n"
|
||||
},
|
||||
workspace: function () {
|
||||
return this.$store.getters["workspaces/getWorkspace"]
|
||||
},
|
||||
enabled: function () {
|
||||
return this.$store.getters["service_status/getEndpoints"]
|
||||
async asyncData({store}) {
|
||||
await store.dispatch("service_status/loadEndpoints")
|
||||
return {
|
||||
enabled: store.getters["service_status/getEnabled"]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async parseStatement() {
|
||||
console.log(this.$data.createTableDef);
|
||||
|
||||
const input = this.$data.createTableDef;
|
||||
|
||||
const chars = new antlr4.InputStream(input);
|
||||
const lexer = new CQL3Lexer.CQL3Lexer(chars);
|
||||
|
||||
lexer.strictMode = false; // do not use js strictMode
|
||||
|
||||
const tokens = new antlr4.CommonTokenStream(lexer);
|
||||
const parser = new CQL3Parser.CQL3Parser(tokens);
|
||||
|
||||
const context = parser.create_table_stmt();
|
||||
|
||||
try {
|
||||
const keyspaceName = context.table_name().keyspace_name().getChild(0).getText()
|
||||
const tableName = context.table_name().table_name_noks().getChild(0).getText()
|
||||
|
||||
const columnDefinitions = context.column_definitions().column_definition();
|
||||
|
||||
let columns = [];
|
||||
let partitionKeys = [];
|
||||
let clusteringKeys = [];
|
||||
columnDefinitions.forEach(columnDef => {
|
||||
if (columnDef.column_name() != null) {
|
||||
columns.push({
|
||||
"name": columnDef.column_name().getText(),
|
||||
"type": columnDef.column_type().getText()
|
||||
})
|
||||
} else {
|
||||
const primaryKeyContext = columnDef.primary_key()
|
||||
if (primaryKeyContext.partition_key() != null) {
|
||||
const partitionKeysContext = primaryKeyContext.partition_key().column_name();
|
||||
partitionKeysContext.map((partitionKey, i) => {
|
||||
const partitionKeyName = partitionKey.getText()
|
||||
const col = {
|
||||
"name": partitionKeyName,
|
||||
"type": columns.filter(x => x.name == partitionKeyName)[0].type
|
||||
}
|
||||
partitionKeys.push(col)
|
||||
})
|
||||
}
|
||||
if (primaryKeyContext.clustering_column().length != 0) {
|
||||
const clusteringKeysContext = primaryKeyContext.clustering_column();
|
||||
clusteringKeysContext.map((clusteringKey, i) => {
|
||||
const clusteringKeyName = clusteringKey.getText()
|
||||
const col = {
|
||||
"name": clusteringKeyName,
|
||||
"type": columns.filter(x => x.name == clusteringKeyName)[0].type
|
||||
}
|
||||
clusteringKeys.push(col)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
columns = columns.filter(col => {
|
||||
return partitionKeys.filter(pk => pk.name == col.name).length == 0 && clusteringKeys.filter(cc => cc.name == col.name).length == 0
|
||||
})
|
||||
|
||||
const allColumns = [].concat(columns, partitionKeys, clusteringKeys)
|
||||
|
||||
this.$data.tableName = tableName;
|
||||
this.$data.keyspaceName = keyspaceName;
|
||||
this.$data.columns = columns;
|
||||
this.$data.clusteringKeys = clusteringKeys;
|
||||
this.$data.partitionKeys = partitionKeys;
|
||||
this.$data.allColumns = allColumns;
|
||||
|
||||
console.log(this.$data)
|
||||
|
||||
console.log(defaultYaml)
|
||||
|
||||
// schema and bindings
|
||||
let createTableStatement = "CREATE TABLE IF NOT EXISTS <<keyspace:" + keyspaceName + ">>." + tableName + " (\n";
|
||||
|
||||
console.log(basictypes)
|
||||
defaultYaml.bindings = {}
|
||||
allColumns.forEach(column => {
|
||||
let recipe = basictypes.bindings[column.type + "val"];
|
||||
if (recipe == undefined) {
|
||||
const chars = new antlr4.InputStream(column.type);
|
||||
const lexer = new CQL3Lexer.CQL3Lexer(chars);
|
||||
lexer.strictMode = false; // do not use js strictMode
|
||||
const tokens = new antlr4.CommonTokenStream(lexer);
|
||||
const parser = new CQL3Parser.CQL3Parser(tokens);
|
||||
|
||||
const typeContext = parser.column_type();
|
||||
const collectionTypeContext = typeContext.data_type().collection_type();
|
||||
const collectionType = collectionTypeContext.children[0].getText();
|
||||
if (collectionType.toLowerCase() == "set") {
|
||||
const type = collectionTypeContext.children[2].getText();
|
||||
recipe = "Set(HashRange(1,<<set-count-" + column.name + ":5>>)," + basictypes.bindings[type + "val"] + ") -> java.util.Set"
|
||||
} else if (collectionType.toLowerCase() == "list") {
|
||||
const type = collectionTypeContext.children[2].getText();
|
||||
recipe = "List(HashRange(1,<<list-count-" + column.name + ":5>>)," + basictypes.bindings[type + "val"] + ") -> java.util.List"
|
||||
|
||||
} else if (collectionType.toLowerCase() == "map") {
|
||||
const type1 = collectionTypeContext.children[2].getText();
|
||||
const type2 = collectionTypeContext.children[4].getText();
|
||||
recipe = "Map(HashRange(1,<<map-count-" + column.name + ":5>>)," + basictypes.bindings[type1 + "val"] + "," + basictypes.bindings[type2 + "val"] + ") -> java.util.Map"
|
||||
} else {
|
||||
alert("Could not generate recipe for type: " + column.type + " for column: " + column.name)
|
||||
}
|
||||
}
|
||||
defaultYaml.bindings[column.name] = recipe
|
||||
createTableStatement = createTableStatement + column.name + " " + column.type + ",\n";
|
||||
})
|
||||
|
||||
let pk = "PRIMARY KEY (("
|
||||
pk = pk + partitionKeys.map(x => x.name).reduce((x, acc) => acc = acc + "," + x)
|
||||
pk = pk + ")"
|
||||
if (clusteringKeys.length > 0) {
|
||||
pk = pk + "," + clusteringKeys.map(x => x.name).reduce((x, acc) => acc = acc + "," + x)
|
||||
}
|
||||
pk = pk + ")"
|
||||
createTableStatement = createTableStatement + pk + "\n);"
|
||||
defaultYaml.blocks[0].statements[0] = {"create-table": createTableStatement}
|
||||
|
||||
//rampup
|
||||
let insertStatement = "INSERT INTO <<keyspace:" + keyspaceName + ">>." + tableName + " (\n";
|
||||
insertStatement = insertStatement + allColumns.map(x => x.name).reduce((x, acc) => acc = acc + ",\n" + x) + "\n) VALUES (\n";
|
||||
insertStatement = insertStatement + allColumns.map(x => "{" + x.name + "}").reduce((x, acc) => acc = acc + ",\n" + x) + "\n);"
|
||||
|
||||
defaultYaml.blocks[1].statements[0] = {"insert-rampup": insertStatement}
|
||||
|
||||
//main-write
|
||||
defaultYaml.blocks[2].statements[0] = {"insert-main": insertStatement}
|
||||
|
||||
//main-read-partition
|
||||
let readPartitionStatement = "SELECT * from <<keyspace:" + keyspaceName + ">>." + tableName + " WHERE ";
|
||||
readPartitionStatement = readPartitionStatement + partitionKeys.map(x => x.name + "={" + x.name + "}").reduce((x, acc) => acc = acc + " AND " + x);
|
||||
let readRowStatement = readPartitionStatement + ";";
|
||||
if (clusteringKeys.length > 0) {
|
||||
readPartitionStatement = readPartitionStatement + " AND " + clusteringKeys.map(x => x.name + "={" + x.name + "}").reduce((x, acc) => acc = acc + " AND " + x);
|
||||
}
|
||||
readPartitionStatement = readPartitionStatement + ";";
|
||||
|
||||
defaultYaml.blocks[3].statements[0] = {"read-partition": readPartitionStatement}
|
||||
|
||||
//main-read-row
|
||||
defaultYaml.blocks[4].statements[0] = {"read-row": readRowStatement}
|
||||
|
||||
defaultYaml.description = this.$data.workloadName
|
||||
|
||||
const yamlOutputText = yamlDumper.dump(defaultYaml)
|
||||
this.blob = new Blob([yamlOutputText], {type: "text/plain;charset=utf-8"});
|
||||
this.parseSuccess = true;
|
||||
} catch (e) {
|
||||
console.log("blur, invalid create table def")
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
},
|
||||
downloadWorkload() {
|
||||
saveAs(this.blob, this.$data.filename);
|
||||
},
|
||||
saveWorkloadToWorkspace() {
|
||||
this.$store.dispatch("workspaces/putFile",{
|
||||
workspace: this.workspace,
|
||||
filename: this.filename,
|
||||
content: this.blob
|
||||
})
|
||||
computed: {
|
||||
workspace: function () {
|
||||
return this.$store.getters["workspaces/getWorkspace"]
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@ -279,33 +84,4 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
/*.container {*/
|
||||
/* margin: 0 auto;*/
|
||||
/* display: flex;*/
|
||||
/* justify-content: center;*/
|
||||
/* align-items: center;*/
|
||||
/* text-align: center;*/
|
||||
/*}*/
|
||||
|
||||
/*.title {*/
|
||||
/* font-family: 'Quicksand', 'Source Sans Pro', -apple-system, BlinkMacSystemFont,*/
|
||||
/* 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;*/
|
||||
/* display: block;*/
|
||||
/* font-weight: 300;*/
|
||||
/* font-size: 100px;*/
|
||||
/* color: #35495e;*/
|
||||
/* letter-spacing: 1px;*/
|
||||
/*}*/
|
||||
|
||||
/*.subtitle {*/
|
||||
/* font-weight: 300;*/
|
||||
/* font-size: 42px;*/
|
||||
/* color: #526488;*/
|
||||
/* word-spacing: 5px;*/
|
||||
/* padding-bottom: 15px;*/
|
||||
/*}*/
|
||||
|
||||
/*.links {*/
|
||||
/* padding-top: 15px;*/
|
||||
/*}*/
|
||||
</style>
|
||||
|
@ -28,12 +28,10 @@
|
||||
|
||||
<v-btn-toggle v-model="toggle_builtins" @change="validateAndSearch()">
|
||||
<v-btn :disabled="this.toggle_workspaces===undefined">
|
||||
<v-container fluid class="d-flex">
|
||||
<v-icon title="include built-in workloads">mdi-folder-open</v-icon>
|
||||
<div class="ma-2">bundled</div>
|
||||
<v-icon v-if="this.toggle_builtins===0">mdi-check</v-icon>
|
||||
|
||||
</v-container>
|
||||
</v-btn>
|
||||
</v-btn-toggle>
|
||||
|
||||
|
@ -3,31 +3,42 @@ import {mapGetters} from "vuex";
|
||||
import endpoints from "@/js/endpoints";
|
||||
|
||||
export const state = () => ({
|
||||
endpoints: {},
|
||||
enabled: false
|
||||
endpoints: null,
|
||||
enabled: null
|
||||
});
|
||||
|
||||
export const getters = {
|
||||
getEndpoints: (state, getters) => {
|
||||
return state.endpoints;
|
||||
},
|
||||
getEnabled: (state, getters) => {
|
||||
return state.enabled;
|
||||
}
|
||||
}
|
||||
|
||||
export const mutations = {
|
||||
setEndpoints(state, endpoints) {
|
||||
state.endpoints = endpoints;
|
||||
},
|
||||
setEnabled(state, enabled) {
|
||||
state.enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
export const actions = {
|
||||
async loadEndpoints(context, reason) {
|
||||
console.log("loading endpoint status because '" + reason + "'")
|
||||
await this.$axios.get(endpoints.url(document, context, "/services/status"))
|
||||
.then(res => {
|
||||
context.commit('setEndpoints', res)
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("axios/nuxt status async error:" + e);
|
||||
})
|
||||
let enabled = context.getters["getEnabled"]
|
||||
if (enabled === null || enabled === undefined) {
|
||||
console.log("loading endpoint status because '" + reason + "'")
|
||||
await this.$axios.get(endpoints.url(document, context, "/services/status"))
|
||||
.then(res => {
|
||||
context.commit('setEndpoints', res.data.endpoints)
|
||||
context.commit('setEnabled', res.data.enabled)
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("axios/nuxt status async error:" + e);
|
||||
})
|
||||
}
|
||||
// else use cache defined status
|
||||
}
|
||||
};
|
||||
|
@ -5,7 +5,8 @@ import endpoints from "@/js/endpoints";
|
||||
export const state = () => ({
|
||||
workspace: 'default',
|
||||
workspaces: [],
|
||||
fileview: []
|
||||
all_ws_files: [],
|
||||
matching_ws_files: []
|
||||
});
|
||||
|
||||
export const getters = {
|
||||
@ -15,8 +16,11 @@ export const getters = {
|
||||
getWorkspaces: (state, getters) => {
|
||||
return state.workspaces;
|
||||
},
|
||||
getFileview: (state, getters) => {
|
||||
return state.fileview;
|
||||
getAllFiles: (state, getters) => {
|
||||
return state.all_ws_files;
|
||||
},
|
||||
getMatchingFiles: (state, getters) => {
|
||||
return state.matching_ws_files;
|
||||
}
|
||||
|
||||
// ...mapGetters(['workspace','workspaces'])
|
||||
@ -29,21 +33,73 @@ export const mutations = {
|
||||
setWorkspaces(state, workspaces) {
|
||||
state.workspaces = workspaces;
|
||||
},
|
||||
setFileview(state, fileview) {
|
||||
state.fileview = fileview;
|
||||
setAllFiles(state, files) {
|
||||
state.all_ws_files = files;
|
||||
},
|
||||
setMatchingFiles(state, files) {
|
||||
state.matching_ws_files = files;
|
||||
}
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
async importUrlToWorkspace(context, params) {
|
||||
console.log("importUrlToWorkspace(ctx," + JSON.stringify(params, null, 2));
|
||||
let workspace = params.workspace;
|
||||
let import_url = params.import_url;
|
||||
let import_as = params.import_as;
|
||||
if (!workspace || !import_url || !import_as) {
|
||||
throw("Unable to save file to workspace without params workspace, import_url, import_as");
|
||||
}
|
||||
this.$axios.$get(import_url)
|
||||
.then(res => {
|
||||
console.log('save url data:' + JSON.stringify(res, null, 2))
|
||||
return res
|
||||
}).then(data => {
|
||||
context.dispatch("putFile", {
|
||||
workspace: workspace,
|
||||
filename: import_as,
|
||||
content: data
|
||||
}).catch((e) => {
|
||||
throw "error while saving data:" + e
|
||||
})
|
||||
})
|
||||
.catch((e) => {
|
||||
throw "axios/nuxt workspaces async error:" + e
|
||||
})
|
||||
},
|
||||
async setWorkspace(context, val) {
|
||||
// console.log("committing setWorkspace:" + JSON.stringify(val));
|
||||
context.commit('setWorkspace', val);
|
||||
await context.dispatch("listWorkspaceFiles", {wsname: val})
|
||||
},
|
||||
async setWorkspaces(context, val) {
|
||||
// console.log("committing setWorkspaces:" + JSON.stringify(val));
|
||||
context.commit('setWorkspaces', val);
|
||||
},
|
||||
async initWorkspaces(context, reason) {
|
||||
async listWorkspaceFiles(context, params) {
|
||||
let wsname = params.wsname;
|
||||
let contains = params.contains;
|
||||
console.log("list params:" + JSON.stringify(params, null, 2))
|
||||
|
||||
let query = "?ls";
|
||||
if (contains) {
|
||||
query = query + "&contains=" + contains
|
||||
}
|
||||
|
||||
await this.$axios.$get(endpoints.url(document, context, "/services/workspaces/" + wsname) + query)
|
||||
.then(res => {
|
||||
console.log("ls ws:" + JSON.stringify(res, null, 2))
|
||||
if (contains) {
|
||||
context.commit("setContains", res["ls"]);
|
||||
} else {
|
||||
context.commit("setFileview", res["ls"])
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
throw "axios/nuxt workspaces async error:" + e
|
||||
})
|
||||
},
|
||||
async loadWorkspaces(context, reason) {
|
||||
// console.log("initializing workspaces because '" + reason + "'")
|
||||
this.$axios.$get(endpoints.url(document, context, "/services/workspaces/"))
|
||||
.then(res => {
|
||||
@ -52,7 +108,7 @@ export const actions = {
|
||||
context.commit('setWorkspaces', res)
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("axios/nuxt workspaces async error:", e);
|
||||
throw "axios/nuxt workspaces async error:" + e
|
||||
})
|
||||
},
|
||||
async putFile(context, params) {
|
||||
@ -60,25 +116,27 @@ export const actions = {
|
||||
let to_filename = params.filename;
|
||||
let to_content = params.content;
|
||||
if (!to_workspace || !to_filename || !to_content) {
|
||||
console.log("params:" + JSON.stringify(params, null, 2))
|
||||
throw("Unable to save file to workspace without params having workspace, filename, content");
|
||||
}
|
||||
const result = await this.$axios.$post(endpoints.url(document, context, "/services/workspaces/" + to_workspace + "/" + to_filename, to_content))
|
||||
console.log("to_content:" + JSON.stringify(to_content, null, 2))
|
||||
const result = await this.$axios.put(endpoints.url(document, context, "/services/workspaces/" + to_workspace + "/" + to_filename), to_content)
|
||||
.then(res => {
|
||||
console.log("axios/vuex workspace put:" + JSON.stringify(res));
|
||||
return res;
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("axios/vuex workspace put:", e)
|
||||
throw "axios/vuex workspace put:" + e
|
||||
});
|
||||
},
|
||||
async activateWorkspace(context, workspace) {
|
||||
const fresh_workspace = await this.$axios.$get(endpoints.url(document, context, "/services/workspaces/" + workspace))
|
||||
async initializeWorkspace(context, workspace) {
|
||||
const fresh_workspace = await this.$axios.$get(endpoints.url(document, context, "/services/workspaces/" + workspace) + "?ls")
|
||||
.then(res => {
|
||||
// console.log("axios/vuex workspace async get:" + JSON.stringify(res))
|
||||
return res;
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("axios/nuxt getWorkspace async error:", e)
|
||||
throw "axios/nuxt getWorkspace async error:" + e
|
||||
})
|
||||
await context.dispatch('initWorkspaces', "workspace '" + workspace + "' added");
|
||||
// await dispatch.initWorkspaces({commit, state, dispatch}, "workspace '" + workspace + "' added")
|
||||
@ -94,7 +152,7 @@ export const actions = {
|
||||
return res;
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("axios/nuxt purgeWorkspace error:", e)
|
||||
throw "axios/nuxt purgeWorkspace error:" + e
|
||||
})
|
||||
const found = this.state.workspaces.workspaces.find(w => w.name === workspace);
|
||||
if (!found) {
|
||||
|
@ -16,6 +16,7 @@ import javax.ws.rs.core.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Path("/services/workspaces")
|
||||
@Singleton
|
||||
@ -79,7 +80,7 @@ public class WorkspacesEndpoint implements WebServiceObject {
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@PUT
|
||||
@Path("/{workspaceName}/{filepath:.+}")
|
||||
@Consumes(MediaType.WILDCARD)
|
||||
@Produces(MediaType.WILDCARD)
|
||||
@ -103,17 +104,20 @@ public class WorkspacesEndpoint implements WebServiceObject {
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response getWorkspaceInfo(
|
||||
@PathParam("workspace") String workspace,
|
||||
@QueryParam("ls") String ls
|
||||
@QueryParam("ls") String ls,
|
||||
@QueryParam("contains") String contains
|
||||
) {
|
||||
try {
|
||||
if (ls!=null && !ls.toLowerCase().equals("false")) {
|
||||
WorkSpace ws = getSvc().getWorkspace(workspace);
|
||||
WorkSpace ws = getSvc().getWorkspace(workspace);
|
||||
WorkspaceView wsview = ws.getWorkspaceView();
|
||||
if (ls != null && !ls.toLowerCase().equals("false")) {
|
||||
List<WorkspaceItemView> listing = ws.getWorkspaceListingView("");
|
||||
return Response.ok(listing).build();
|
||||
} else {
|
||||
WorkspaceView workpaceView = getSvc().getWorkspaceView(workspace);
|
||||
return Response.ok(workpaceView).build();
|
||||
if (contains != null) {
|
||||
listing = listing.stream().filter(i -> i.contains(contains)).collect(Collectors.toList());
|
||||
}
|
||||
wsview.setListing(listing);
|
||||
}
|
||||
return Response.ok(wsview).build();
|
||||
} catch (Exception e) {
|
||||
return Response.serverError().entity(e.getMessage()).build();
|
||||
}
|
||||
@ -128,7 +132,7 @@ public class WorkspacesEndpoint implements WebServiceObject {
|
||||
@QueryParam("ls") String ls) {
|
||||
|
||||
try {
|
||||
if (ls!=null && !ls.toLowerCase().equals("false")) {
|
||||
if (ls != null && !ls.toLowerCase().equals("false")) {
|
||||
WorkSpace ws = getSvc().getWorkspace(workspace);
|
||||
List<WorkspaceItemView> listing = ws.getWorkspaceListingView(filename);
|
||||
return Response.ok(listing).build();
|
||||
|
@ -11,6 +11,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.List;
|
||||
|
||||
public class WorkspaceView {
|
||||
|
||||
@ -25,6 +26,9 @@ public class WorkspaceView {
|
||||
private final Path workspaceRoot;
|
||||
private Summary summary;
|
||||
|
||||
@JsonProperty("ls")
|
||||
private List<WorkspaceItemView> listing = null;
|
||||
|
||||
public WorkspaceView(Path workspaceRoot) {
|
||||
this.workspaceRoot = workspaceRoot;
|
||||
}
|
||||
@ -56,13 +60,17 @@ public class WorkspaceView {
|
||||
return this.summary;
|
||||
}
|
||||
|
||||
public void setListing(List<WorkspaceItemView> listing) {
|
||||
this.listing = listing;
|
||||
}
|
||||
|
||||
public final static class Summary extends SimpleFileVisitor<Path> {
|
||||
|
||||
private final Path root;
|
||||
|
||||
public long total_bytes = 0L;
|
||||
public long total_files = 0L;
|
||||
public long last_changed_epoch =Long.MIN_VALUE;
|
||||
public long last_changed_epoch = Long.MIN_VALUE;
|
||||
public String last_changed_filename = "";
|
||||
|
||||
public String getLast_changed_ago() {
|
||||
|
Loading…
Reference in New Issue
Block a user