Web: Replace Vue 2 with Vue 3 webapp

Replace the Vue v2 webapp with a Vue v3 one, and embed the OpenAPI
client in the webapp itself (instead of being its own npm project).

- Vue v2.x -> v3.x
- Tabulator v4.x -> v5.1
- Moment JS -> replaced with Luxon JS
- Vue CLI/UI -> replaced with Vite
This commit is contained in:
Sybren A. Stüvel 2022-04-12 12:34:49 +02:00
parent c0b2c6c234
commit 555c935790
123 changed files with 2222 additions and 36596 deletions

View File

@ -63,7 +63,8 @@ generate-py:
generate-js:
# The generator doesn't consistently overwrite existing files, nor does it
# remove no-longer-generated files.
rm -rf web/manager-api
rm -rf web/app/src/manager-api
rm -rf web/_tmp-manager-api-javascript
# See https://openapi-generator.tech/docs/generators/javascript for the options.
# Version '0.0.0' is used as NPM doesn't like Git hashes as versions.
@ -75,23 +76,20 @@ generate-js:
generate \
-i pkg/api/flamenco-manager.yaml \
-g javascript \
-o web/manager-api \
-o web/_tmp-manager-api-javascript \
--http-user-agent "Flamenco/${VERSION} / webbrowser" \
-p projectName=flamenco-manager \
-p projectVersion="0.0.0" \
-p apiPackage="${JS_API_PKG_NAME}" \
-p disallowAdditionalPropertiesIfNotPresent=false \
-p usePromises=true \
-p moduleName=flamencoManager \
-p modelPropertyNaming=original
-p moduleName=flamencoManager
# The generator outputs files so that we can write our own tests. We don't,
# though, so it's better to just remove those placeholders.
rm -rf web/manager-api/test
# Ensure that the API package can actually be imported by the webapp (if
# symlinks are in place).
cd web/manager-api && npm install && npm run build
# Cherry-pick the generated sources, and remove everything else.
# The only relevant bit is that the generated code depends on `superagent`,
# which is listed in our `.
mv web/_tmp-manager-api-javascript/src web/app/src/manager-api
rm -rf web/_tmp-manager-api-javascript
version:
@echo "OS : ${OS}"

View File

@ -137,6 +137,7 @@ function authorRenderTasks(settings, renderDir, renderOutput) {
function authorCreateVideoTask(settings, renderDir) {
if (settings.images_or_video == "video") {
print("Not authoring video task, render output is already a video");
return;
}
if (ffmpegIncompatibleImageFormats.has(settings.format)) {
print("Not authoring video task, FFmpeg-incompatible render output")

View File

@ -1 +0,0 @@
node_modules/flamenco-manager/dist

14
web/app/.eslintrc.cjs Normal file
View File

@ -0,0 +1,14 @@
/* eslint-env node */
require("@rushstack/eslint-patch/modern-module-resolution");
module.exports = {
"root": true,
"extends": [
"plugin:vue/vue3-essential",
"eslint:recommended",
"@vue/eslint-config-prettier"
],
"env": {
"vue/setup-compiler-macros": true
}
}

28
web/app/.gitignore vendored Normal file
View File

@ -0,0 +1,28 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

35
web/app/README.md Normal file
View File

@ -0,0 +1,35 @@
# flamenco-manager
This template should help get you started developing with Vue 3 in Vite.
## Recommended IDE Setup
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.vscode-typescript-vue-plugin).
## Customize configuration
See [Vite Configuration Reference](https://vitejs.dev/config/).
## Project Setup
```sh
npm install
```
### Compile and Hot-Reload for Development
```sh
npm run dev
```
### Compile and Minify for Production
```sh
npm run build
```
### Lint with [ESLint](https://eslint.org/)
```sh
npm run lint
```

13
web/app/index.html Normal file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

27301
web/app/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,10 @@
{
"name": "flamenco-manager-web-frontend",
"version": "3.0.0",
"name": "flamenco-manager",
"version": "0.0.3",
"private": true,
"author": {
"name": "Sybren A. Stüvel"
},
"dependencies": {
"bootstrap-vue": "^2.21.2",
"core-js": "^3.6.5",
"moment": "^2.29.2",
"sass": "^1.50.0",
"sass-loader": "^10",
"socket.io-client": "2.4.0",
"vue": "^2.6.11",
"vue-tabulator": "^1.3.0"
},
"licenses": [
{
"type": "GPL-3.0",
@ -22,36 +12,26 @@
}
],
"scripts": {
"serve": "vue-cli-service serve --port 8081",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
"dev": "vite --port 8081",
"build": "vite build",
"preview": "vite preview --port 5050",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
},
"dependencies": {
"luxon": "^2.3.1",
"socket.io-client": "2",
"superagent": "^7.1.2",
"tabulator-tables": "^5.1.8",
"vue": "^3.2.31",
"vue-router": "^4.0.14"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
"@rushstack/eslint-patch": "^1.1.0",
"@vitejs/plugin-vue": "^2.3.1",
"@vue/eslint-config-prettier": "^7.0.0",
"eslint": "^8.5.0",
"eslint-plugin-vue": "^8.2.0",
"prettier": "^2.5.1",
"vite": "^2.9.1"
}
}

View File

@ -1,17 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -1,47 +1,35 @@
<template>
<div id="app">
<flamenco-navbar></flamenco-navbar>
<br />
<flamenco-jobs-table ref="jobsTable" :apiClient="apiClient" />
<chat-chatbox
@sendMessage="sendMessage"
:chatHistory="messages"
/>
<jobs-listener
ref="jobsListener"
:websocketURL="websocketURL"
@jobUpdate="onJobUpdate"
@message="onChatMessage"
@reconnected="onReconnected"
/>
<header>Flamenco</header>
<div class="col-1">
<jobs-table ref="jobsTable" :apiClient="apiClient" />
</div>
<div class="col-2">Job Details</div>
<div class="col-3">Task Details</div>
<footer>Footer
<update-listener ref="updateListener" :websocketURL="websocketURL" @jobUpdate="onJobUpdate" @message="onChatMessage"
@reconnected="onReconnected" />
</footer>
</template>
<script>
import FlamencoNavbar from "./components/FlamencoNavbar.vue";
import FlamencoJobsTable from "./components/FlamencoJobsTable.vue";
import ChatChatbox from "./components/ChatChatbox.vue";
import JobsListener from "./components/JobsListener.vue";
import * as urls from './urls'
import { ApiClient } from './manager-api';
import JobsTable from './components/JobsTable.vue'
import UpdateListener from './components/UpdateListener.vue'
export default {
name: "FlamencoWebApp",
name: 'App',
components: {
FlamencoNavbar,
FlamencoJobsTable,
ChatChatbox,
JobsListener,
JobsTable, UpdateListener,
},
props: ["apiClient"],
data: () => {
return {
websocketURL: "ws://localhost:8080",
apiClient: new ApiClient(urls.api()),
websocketURL: urls.ws(),
messages: [],
};
},
mounted: function () {
},
mounted() { },
methods: {
sendMessage(message) {
this.$refs.jobsListener.sendBroadcastMessage("typer", message);
@ -64,22 +52,53 @@ export default {
this.$refs.jobsTable.onReconnected();
},
},
};
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
@import "tabulator-tables/dist/css/tabulator.min.css";
body {
margin: 0;
}
html,
body,
#app,
.card {
height: 100%;
#app {
font-family: 'Noto Sans', sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
display: grid;
width: 100%;
height: 100vh;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 20px 1fr 10px;
grid-gap: 1rem;
grid-template-areas:
"header header header"
"col-1 col-2 col-3"
"footer footer footer";
}
header {
grid-area: header;
background-color: #333;
color: #EEE;
}
.col-1 {
grid-area: col-1;
}
.col-2 {
grid-area: col-2;
}
.col-3 {
grid-area: col-3;
}
footer {
grid-area: footer;
}
</style>

View File

@ -0,0 +1,74 @@
/* color palette from <https://github.com/vuejs/theme> */
:root {
--vt-c-white: #ffffff;
--vt-c-white-soft: #f8f8f8;
--vt-c-white-mute: #f2f2f2;
--vt-c-black: #181818;
--vt-c-black-soft: #222222;
--vt-c-black-mute: #282828;
--vt-c-indigo: #2c3e50;
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
--vt-c-text-light-1: var(--vt-c-indigo);
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
--vt-c-text-dark-1: var(--vt-c-white);
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
}
/* semantic color variables for this project */
:root {
--color-background: var(--vt-c-white);
--color-background-soft: var(--vt-c-white-soft);
--color-background-mute: var(--vt-c-white-mute);
--color-border: var(--vt-c-divider-light-2);
--color-border-hover: var(--vt-c-divider-light-1);
--color-heading: var(--vt-c-text-light-1);
--color-text: var(--vt-c-text-light-1);
--section-gap: 160px;
}
@media (prefers-color-scheme: dark) {
:root {
--color-background: var(--vt-c-black);
--color-background-soft: var(--vt-c-black-soft);
--color-background-mute: var(--vt-c-black-mute);
--color-border: var(--vt-c-divider-dark-2);
--color-border-hover: var(--vt-c-divider-dark-1);
--color-heading: var(--vt-c-text-dark-1);
--color-text: var(--vt-c-text-dark-2);
}
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
position: relative;
font-weight: normal;
}
body {
min-height: 100vh;
color: var(--color-text);
background: var(--color-background);
transition: color 0.5s, background-color 0.5s;
line-height: 1.6;
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
font-size: 15px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69" xmlns:v="https://vecta.io/nano"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>

After

Width:  |  Height:  |  Size: 308 B

View File

@ -1,61 +0,0 @@
<template>
<b-container>
<b-card>
<div class="chatbox">
<b-row
class="no-gutters"
align-h="start"
v-for="(message, inx) in chatHistory"
:key="inx"
>
<b-col class="no-gutters" cols="8">
<div>
<p class="received-chat">{{ message }}</p>
</div>
</b-col>
</b-row>
</div>
<ChatMessageBox @sendMessage="(msg) => $emit('sendMessage', msg)" />
</b-card>
</b-container>
</template>
<script>
import ChatMessageBox from "./ChatMessagebox.vue";
export default {
emits: ["sendMessage"],
props: ["chatHistory"],
components: {
ChatMessageBox,
},
};
</script>
<style scoped>
.container {
height: 25ex;
}
.chatbox {
padding: 10px;
height: calc(100% - 35px);
overflow-y: auto;
/* background-image: url("https://i0.wp.com/www.tortugacreative.com/wp-content/uploads/social-media-background-dark-2.png?ssl=1"); */
}
.sender-name {
margin: 0px;
}
.chat {
background-color: lightgreen;
padding: 10px;
border-top-left-radius: 10px;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
.received-chat {
background-color: lightblue;
padding: 10px;
border-top-right-radius: 10px;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
</style>

View File

@ -1,17 +0,0 @@
<template>
<b-card title="Chat-App">
<b-form>
<label class="sr-only" for="inline-form-input-username">Username</label>
<b-input-group prepend="@" class="mb-2 mr-sm-2 mb-sm-0">
<b-form-input
id="inline-form-input-username"
placeholder="Username"
v-model.trim="username"
></b-form-input>
<b-button @click="joinRoom">Join</b-button>
</b-input-group>
</b-form>
</b-card>
</template>
<style scoped></style>

View File

@ -1,38 +0,0 @@
<template>
<b-input-group class="mb-2 mr-sm-2 mb-sm-0">
<b-form-input
placeholder="type here.."
v-model.trim="newMsg"
@keyup.enter="sendMessage"
></b-form-input>
<b-button
size="md"
variant="primary"
class="mb-2"
@click="sendMessage"
:disabled="!newMsg"
>
Send
</b-button>
</b-input-group>
</template>
<script>
export default {
emits: ["sendMessage"],
data() {
return {
newMsg: "",
};
},
methods: {
sendMessage() {
if (!this.newMsg) return;
console.log("emitting message to send:", this.newMsg);
this.$emit("sendMessage", this.newMsg);
this.newMsg = "";
},
},
};
</script>

View File

@ -1,123 +0,0 @@
<template>
<div class="flamenco-jobs-table">
<JobsTabulator
ref="tabulator"
:options="options"
/>
</div>
</template>
<script>
/**
* NOTE: the <JobsTabulator> component does NOT have a v-model attribute.
* Instead of using Vue, data updates are handled on the Tabulator instance
* directly. This gives more control over replacing data & updating existing
* entries.
*/
import moment from "moment";
import { TabulatorComponent } from "vue-tabulator";
const flamencoManager = require('flamenco-manager');
export default {
props: ["apiClient"],
components: {
JobsTabulator: TabulatorComponent,
},
data: () => {
const options = {
// See pkg/api/flamenco-manager.yaml, schemas Job and JobUpdate.
columns: [
{ title: 'ID', field: 'id', sorter: 'string'},
{ title: 'Name', field: 'name', sorter: 'string' },
{ title: 'Status', field: 'status', sorter: 'string', width: 100 },
{ title: 'Type', field: 'type', sorter: 'string', width: 150 },
{ title: 'Prio', field: 'priority', sorter: 'number'},
{ title: 'Updated', field: 'updated', sorter: 'datetime',
sorterParams: {
format: "YYYY-MM-DD hh:mm:ss", // Format suitable for sorting chronologically.
alignEmptyValues: "top",
},
formatter: function (cell, formatterParams) { // eslint-disable-line no-unused-vars
const updated = moment(cell.getData().updated);
const now = moment();
const ageInDays = now.diff(updated, 'days');
if (ageInDays > 14)
return updated.format('YYYY-MM-DD HH:mm:ss')
return updated.fromNow();
}
},
],
initialSort:[
{column:"updated", dir:"desc"},
],
pagination: "local",
paginationSize: 10,
};
return {
options: options,
};
},
mounted: function() {
// Allow testing from the JS console:
// jobsTableVue.processJobUpdate({id: "1e42bbf8-6a17-49b9-8a2a-2c80c6532465", status: "heyy", updated: moment().format(), previous_status: "uuuuh", name: "Updated manually"});
// jobsTableVue.processJobUpdate({id: "7c26cac3-1811-42a8-8577-cd20faeb01a4", status: "heyy", updated: moment().format()});
window.jobsTableVue = this;
this.fetchAllJobs();
},
methods: {
onReconnected() {
// If the connection to the backend was lost, we have likely missed some
// updates. Just fetch the data and start from scratch.
this.fetchAllJobs();
},
tabulator: function() {
const tab = this.$refs.tabulator.getInstance();
return tab;
},
sortData: function() {
const tab = this.tabulator();
tab.setSort(tab.getSorters()); // This triggers re-sorting.
},
fetchAllJobs: function() {
const JobsApi = new flamencoManager.JobsApi(this.apiClient);
const jobsQuery = {};
JobsApi.queryJobs(jobsQuery).then(this.onJobsFetched, function(error) {
// TODO: error handling.
console.error(error);
});
},
onJobsFetched: function(data) {
this.tabulator().setData(data.jobs);
},
processJobUpdate: function(jobUpdate) {
// updateData() will only overwrite properties that are actually set on
// jobUpdate, and leave the rest as-is.
this.tabulator().updateData([jobUpdate])
.then(this.sortData);
},
processNewJob: function(jobUpdate) {
console.log("processNewJob:", jobUpdate);
// The update doesn't have all the info we need, so just fetch the job via an API call.
const JobsApi = new flamencoManager.JobsApi(this.apiClient);
JobsApi.fetchJob(jobUpdate.id).then((job) => {
console.log('API called successfully. Returned data: ' + job);
console.log("Fetched job:", JSON.parse(JSON.stringify(job)));
this.tabulator().addData([job])
.then(this.sortData);
}, (error) => {
console.error(error);
});
},
}
};
</script>
<style lang='scss'>
@import "~vue-tabulator/dist/scss/bootstrap/tabulator_bootstrap4";
.flamenco-jobs-table {
min-height: 50%;
border: thick solid fuchsia;
}
</style>

View File

@ -1,5 +0,0 @@
<template>
<b-navbar toggleable type="dark" variant="dark">
<b-navbar-brand href="#">Flamenco</b-navbar-brand>
</b-navbar>
</template>

View File

@ -0,0 +1,43 @@
<script setup>
defineProps({
msg: {
type: String,
required: true
}
})
</script>
<template>
<div class="greetings">
<h1 class="green">{{ msg }}</h1>
<h3>
Youve successfully created a project with
<a target="_blank" href="https://vitejs.dev/">Vite</a> +
<a target="_blank" href="https://vuejs.org/">Vue 3</a>.
</h3>
</div>
</template>
<style scoped>
h1 {
font-weight: 500;
font-size: 2.6rem;
top: -10px;
}
h3 {
font-size: 1.2rem;
}
.greetings h1,
.greetings h3 {
text-align: center;
}
@media (min-width: 1024px) {
.greetings h1,
.greetings h3 {
text-align: left;
}
}
</style>

View File

@ -0,0 +1,115 @@
<template>
<div class="job-list" id="flamenco_job_list">
</div>
</template>
<script lang="js">
import { TabulatorFull as Tabulator } from 'tabulator-tables';
import { DateTime } from "luxon";
import {
JobsApi,
} from '../manager-api'
export default {
props: ["apiClient"],
data: () => {
const options = {
// See pkg/api/flamenco-manager.yaml, schemas Job and JobUpdate.
columns: [
{ title: 'ID', field: 'id', sorter: 'string', width: "15ex" },
{ title: 'Name', field: 'name', sorter: 'string' },
{ title: 'Status', field: 'status', sorter: 'string', width: 100 },
{ title: 'Type', field: 'type', sorter: 'string', width: 150 },
{ title: 'Prio', field: 'priority', sorter: 'number' },
{
title: 'Updated', field: 'updated',
sorter: 'alphanum', sorterParams: { alignEmptyValues: "top" },
formatter(cell, formatterParams) { // eslint-disable-line no-unused-vars
const cellValue = cell.getData().updated;
let updated = null;
if (cellValue instanceof Date) {
updated = DateTime.fromJSDate(cellValue);
} else {
updated = DateTime.fromISO(cellValue);
}
const now = DateTime.local();
const ageInDays = now.diff(updated).as('days');
if (ageInDays > 14)
return updated.toLocaleString(DateTime.DATE_MED_WITH_WEEKDAY);
return updated.toRelative();
}
},
],
initialSort: [
{ column: "updated", dir: "desc" },
],
height: "80%",
data: [],
};
return {
options: options,
};
},
mounted() {
// Allow testing from the JS console:
// jobsTableVue.processJobUpdate({id: "ad0a5a00-5cb8-4e31-860a-8a405e75910e", status: "heyy", updated: DateTime.local().toISO(), previous_status: "uuuuh", name: "Updated manually"});
// jobsTableVue.processJobUpdate({id: "ad0a5a00-5cb8-4e31-860a-8a405e75910e", status: "heyy", updated: DateTime.local().toISO()});
window.jobsTableVue = this;
this.tabulator = new Tabulator('#flamenco_job_list', this.options);
this.fetchAllJobs();
},
methods: {
onReconnected() {
// If the connection to the backend was lost, we have likely missed some
// updates. Just fetch the data and start from scratch.
this.fetchAllJobs();
},
sortData() {
const tab = this.tabulator;
tab.setSort(tab.getSorters()); // This triggers re-sorting.
},
fetchAllJobs() {
if (this.apiClient === undefined) {
throw "no apiClient set on JobsTable component";
}
const jobsApi = new JobsApi(this.apiClient);
const jobsQuery = {};
jobsApi.queryJobs(jobsQuery).then(this.onJobsFetched, function (error) {
// TODO: error handling.
console.error(error);
});
},
onJobsFetched(data) {
this.tabulator.setData(data.jobs);
},
processJobUpdate(jobUpdate) {
// updateData() will only overwrite properties that are actually set on
// jobUpdate, and leave the rest as-is.
this.tabulator.updateData([jobUpdate])
.then(this.sortData);
},
processNewJob(jobUpdate) {
console.log("processNewJob:", jobUpdate);
// The update doesn't have all the info we need, so just fetch the job via an API call.
const jobsApi = new JobsApi(this.apiClient);
jobsApi.fetchJob(jobUpdate.id).then((job) => {
console.log('API called successfully. Returned data: ' + job);
console.log("Fetched job:", JSON.parse(JSON.stringify(job)));
this.tabulator.addData([job])
.then(this.sortData);
}, (error) => {
console.error(error);
});
},
}
};
</script>
<style scoped>
.job-list {
border: thick solid fuchsia;
font-family: 'Noto Mono', monospace;
font-size: smaller;
}
</style>

View File

@ -0,0 +1,84 @@
<script setup>
import WelcomeItem from './WelcomeItem.vue'
import DocumentationIcon from './icons/IconDocumentation.vue'
import ToolingIcon from './icons/IconTooling.vue'
import EcosystemIcon from './icons/IconEcosystem.vue'
import CommunityIcon from './icons/IconCommunity.vue'
import SupportIcon from './icons/IconSupport.vue'
</script>
<template>
<WelcomeItem>
<template #icon>
<DocumentationIcon />
</template>
<template #heading>Documentation</template>
Vues
<a target="_blank" href="https://vuejs.org/">official documentation</a>
provides you with all information you need to get started.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<ToolingIcon />
</template>
<template #heading>Tooling</template>
This project is served and bundled with
<a href="https://vitejs.dev/guide/features.html" target="_blank">Vite</a>. The recommended IDE
setup is <a href="https://code.visualstudio.com/" target="_blank">VSCode</a> +
<a href="https://github.com/johnsoncodehk/volar" target="_blank">Volar</a>. If you need to test
your components and web pages, check out
<a href="https://www.cypress.io/" target="_blank">Cypress</a> and
<a href="https://docs.cypress.io/guides/component-testing/introduction" target="_blank"
>Cypress Component Testing</a
>.
<br />
More instructions are available in <code>README.md</code>.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<EcosystemIcon />
</template>
<template #heading>Ecosystem</template>
Get official tools and libraries for your project:
<a target="_blank" href="https://pinia.vuejs.org/">Pinia</a>,
<a target="_blank" href="https://router.vuejs.org/">Vue Router</a>,
<a target="_blank" href="https://test-utils.vuejs.org/">Vue Test Utils</a>, and
<a target="_blank" href="https://github.com/vuejs/devtools">Vue Dev Tools</a>. If you need more
resources, we suggest paying
<a target="_blank" href="https://github.com/vuejs/awesome-vue">Awesome Vue</a>
a visit.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<CommunityIcon />
</template>
<template #heading>Community</template>
Got stuck? Ask your question on
<a target="_blank" href="https://chat.vuejs.org">Vue Land</a>, our official Discord server, or
<a target="_blank" href="https://stackoverflow.com/questions/tagged/vue.js">StackOverflow</a>.
You should also subscribe to
<a target="_blank" href="https://news.vuejs.org">our mailing list</a> and follow the official
<a target="_blank" href="https://twitter.com/vuejs">@vuejs</a>
twitter account for latest news in the Vue world.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<SupportIcon />
</template>
<template #heading>Support Vue</template>
As an independent project, Vue relies on community backing for its sustainability. You can help
us by
<a target="_blank" href="https://vuejs.org/sponsor/">becoming a sponsor</a>.
</WelcomeItem>
</template>

View File

@ -1,5 +1,5 @@
<template>
<span />
<span></span>
</template>
<script>
@ -14,6 +14,10 @@ export default {
}
},
mounted: function () {
if (!this.websocketURL) {
console.log("UpdateListener: no websocketURL given, cannot do anything");
return;
}
this.connectToWebsocket();
},
beforeDestroy: function () {
@ -27,11 +31,20 @@ export default {
this.socket = io(this.websocketURL, {
transports: ["websocket"],
});
this.socket.on('connect_error', (error) => {
console.log("socketIO connection error:", error);
});
this.socket.on('error', (error) => {
console.log("socketIO error:", error);
});
this.socket.on('connect_timeout', (timeout) => {
console.log("socketIO connection timeout:", timeout);
});
this.socket.on("reconnect", (attemptNumber) => {
console.log("socketIO reconnected after", attemptNumber, "attempts");
this.$emit("reconnected");
})
});
this.socket.on("/jobs", (jobUpdate) => {
this.$emit("jobUpdate", jobUpdate);
@ -41,6 +54,9 @@ export default {
this.socket.on("/message", (message) => {
this.$emit("message", message);
});
// Only connect after the handlers have been set up.
// this.socket.open();
},
disconnectWebsocket() {

View File

@ -0,0 +1,86 @@
<template>
<div class="item">
<i>
<slot name="icon"></slot>
</i>
<div class="details">
<h3>
<slot name="heading"></slot>
</h3>
<slot></slot>
</div>
</div>
</template>
<style scoped>
.item {
margin-top: 2rem;
display: flex;
}
.details {
flex: 1;
margin-left: 1rem;
}
i {
display: flex;
place-items: center;
place-content: center;
width: 32px;
height: 32px;
color: var(--color-text);
}
h3 {
font-size: 1.2rem;
font-weight: 500;
margin-bottom: 0.4rem;
color: var(--color-heading);
}
@media (min-width: 1024px) {
.item {
margin-top: 0;
padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
}
i {
top: calc(50% - 25px);
left: -26px;
position: absolute;
border: 1px solid var(--color-border);
background: var(--color-background);
border-radius: 8px;
width: 50px;
height: 50px;
}
.item:before {
content: ' ';
border-left: 1px solid var(--color-border);
position: absolute;
left: 0;
bottom: calc(50% + 25px);
height: calc(50% - 25px);
}
.item:after {
content: ' ';
border-left: 1px solid var(--color-border);
position: absolute;
left: 0;
top: calc(50% + 25px);
height: calc(50% - 25px);
}
.item:first-of-type:before {
display: none;
}
.item:last-of-type:after {
display: none;
}
}
</style>

View File

@ -0,0 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
<path
d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
/>
</svg>
</template>

View File

@ -0,0 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
<path
d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
/>
</svg>
</template>

View File

@ -0,0 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
<path
d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
/>
</svg>
</template>

View File

@ -0,0 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
<path
d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
/>
</svg>
</template>

View File

@ -0,0 +1,19 @@
<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
aria-hidden="true"
role="img"
class="iconify iconify--mdi"
width="24"
height="24"
preserveAspectRatio="xMidYMid meet"
viewBox="0 0 24 24"
>
<path
d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
fill="currentColor"
></path>
</svg>
</template>

View File

@ -1,52 +1,31 @@
import Vue from 'vue'
import { createApp } from 'vue'
import App from './App.vue'
import {
FormInputPlugin,
NavbarPlugin,
LayoutPlugin,
IconsPlugin,
BCard,
BInputGroup,
BButton,
} from "bootstrap-vue";
import router from './router'
import URLs from './urls'
import "bootstrap/dist/css/bootstrap.css";
import "bootstrap-vue/dist/bootstrap-vue.css";
let flamencoManager = require('flamenco-manager');
let apiClient = new flamencoManager.ApiClient(URLs.api);
// Ensure Tabulator can find `moment`, which it needs for sorting by
// Ensure Tabulator can find `luxon`, which it needs for sorting by
// date/time/datetime.
import moment from 'moment';
window.moment = moment;
import { DateTime } from 'luxon';
window.DateTime = DateTime;
// let query = new flamencoManager.JobsQuery();
// // query.status_in = ["active"];
// query.metadata = {project: "Heist"};
// // Example of how to use the Flamenco Manager API:
// import * as urls from './urls'
// import {
// ApiClient,
// MetaApi,
// } from './manager-api'
// let JobsApi = new flamencoManager.JobsApi(apiClient);
// JobsApi.queryJobs(query).then(function(data) {
// console.log('API called successfully.');
// console.log(data);
// }, function(error) {
// console.error(error);
// });
// let apiClient = new ApiClient(urls.api());
// console.log('ApiClient:', apiClient);
// const metaAPI = new MetaApi(apiClient);
// console.log("metaAPI:", metaAPI);
// metaAPI.getVersion().then(function (version) {
// console.log("version:", version);
// })
// metaAPI.getConfiguration().then(function (config) {
// console.log("config:", config);
// })
Vue.config.productionTip = false
Vue.use(FormInputPlugin);
Vue.use(NavbarPlugin);
Vue.use(LayoutPlugin);
Vue.component("b-card", BCard);
Vue.component("b-input-group", BInputGroup);
Vue.component("b-button", BButton);
Vue.use(IconsPlugin);
var vueApp = new Vue(App);
vueApp.websocketURL = URLs.ws;
vueApp.apiClient = apiClient;
vueApp.$mount("#app");
const app = createApp(App)
app.use(router)
app.mount('#app')

View File

@ -55,7 +55,7 @@ class ApiClient {
* @default {}
*/
this.defaultHeaders = {
'User-Agent': 'Flamenco/930d7497-dirty / webbrowser'
'User-Agent': 'Flamenco/fc363732-dirty / webbrowser'
};
/**

View File

@ -42,18 +42,18 @@ export default class JobsApi {
/**
* Fetch info about the job.
* @param {String} job_id
* @param {String} jobId
* @return {Promise} a {@link https://www.promisejs.org/|Promise}, with an object containing data of type {@link module:model/Job} and HTTP response
*/
fetchJobWithHttpInfo(job_id) {
fetchJobWithHttpInfo(jobId) {
let postBody = null;
// verify the required parameter 'job_id' is set
if (job_id === undefined || job_id === null) {
throw new Error("Missing the required parameter 'job_id' when calling fetchJob");
// verify the required parameter 'jobId' is set
if (jobId === undefined || jobId === null) {
throw new Error("Missing the required parameter 'jobId' when calling fetchJob");
}
let pathParams = {
'job_id': job_id
'job_id': jobId
};
let queryParams = {
};
@ -75,11 +75,11 @@ export default class JobsApi {
/**
* Fetch info about the job.
* @param {String} job_id
* @param {String} jobId
* @return {Promise} a {@link https://www.promisejs.org/|Promise}, with data of type {@link module:model/Job}
*/
fetchJob(job_id) {
return this.fetchJobWithHttpInfo(job_id)
fetchJob(jobId) {
return this.fetchJobWithHttpInfo(jobId)
.then(function(response_and_data) {
return response_and_data.data;
});
@ -127,14 +127,14 @@ export default class JobsApi {
/**
* Fetch list of jobs.
* @param {module:model/JobsQuery} JobsQuery Specification of which jobs to get.
* @param {module:model/JobsQuery} jobsQuery Specification of which jobs to get.
* @return {Promise} a {@link https://www.promisejs.org/|Promise}, with an object containing data of type {@link module:model/JobsQueryResult} and HTTP response
*/
queryJobsWithHttpInfo(JobsQuery) {
let postBody = JobsQuery;
// verify the required parameter 'JobsQuery' is set
if (JobsQuery === undefined || JobsQuery === null) {
throw new Error("Missing the required parameter 'JobsQuery' when calling queryJobs");
queryJobsWithHttpInfo(jobsQuery) {
let postBody = jobsQuery;
// verify the required parameter 'jobsQuery' is set
if (jobsQuery === undefined || jobsQuery === null) {
throw new Error("Missing the required parameter 'jobsQuery' when calling queryJobs");
}
let pathParams = {
@ -159,11 +159,11 @@ export default class JobsApi {
/**
* Fetch list of jobs.
* @param {module:model/JobsQuery} JobsQuery Specification of which jobs to get.
* @param {module:model/JobsQuery} jobsQuery Specification of which jobs to get.
* @return {Promise} a {@link https://www.promisejs.org/|Promise}, with data of type {@link module:model/JobsQueryResult}
*/
queryJobs(JobsQuery) {
return this.queryJobsWithHttpInfo(JobsQuery)
queryJobs(jobsQuery) {
return this.queryJobsWithHttpInfo(jobsQuery)
.then(function(response_and_data) {
return response_and_data.data;
});
@ -172,14 +172,14 @@ export default class JobsApi {
/**
* Submit a new job for Flamenco Manager to execute.
* @param {module:model/SubmittedJob} SubmittedJob Job to submit
* @param {module:model/SubmittedJob} submittedJob Job to submit
* @return {Promise} a {@link https://www.promisejs.org/|Promise}, with an object containing data of type {@link module:model/Job} and HTTP response
*/
submitJobWithHttpInfo(SubmittedJob) {
let postBody = SubmittedJob;
// verify the required parameter 'SubmittedJob' is set
if (SubmittedJob === undefined || SubmittedJob === null) {
throw new Error("Missing the required parameter 'SubmittedJob' when calling submitJob");
submitJobWithHttpInfo(submittedJob) {
let postBody = submittedJob;
// verify the required parameter 'submittedJob' is set
if (submittedJob === undefined || submittedJob === null) {
throw new Error("Missing the required parameter 'submittedJob' when calling submitJob");
}
let pathParams = {
@ -204,11 +204,11 @@ export default class JobsApi {
/**
* Submit a new job for Flamenco Manager to execute.
* @param {module:model/SubmittedJob} SubmittedJob Job to submit
* @param {module:model/SubmittedJob} submittedJob Job to submit
* @return {Promise} a {@link https://www.promisejs.org/|Promise}, with data of type {@link module:model/Job}
*/
submitJob(SubmittedJob) {
return this.submitJobWithHttpInfo(SubmittedJob)
submitJob(submittedJob) {
return this.submitJobWithHttpInfo(submittedJob)
.then(function(response_and_data) {
return response_and_data.data;
});

View File

@ -42,14 +42,14 @@ export default class ShamanApi {
/**
* Create a directory, and symlink the required files into it. The files must all have been uploaded to Shaman before calling this endpoint.
* @param {module:model/ShamanCheckout} ShamanCheckout Set of files to check out.
* @param {module:model/ShamanCheckout} shamanCheckout Set of files to check out.
* @return {Promise} a {@link https://www.promisejs.org/|Promise}, with an object containing data of type {@link module:model/ShamanCheckoutResult} and HTTP response
*/
shamanCheckoutWithHttpInfo(ShamanCheckout) {
let postBody = ShamanCheckout;
// verify the required parameter 'ShamanCheckout' is set
if (ShamanCheckout === undefined || ShamanCheckout === null) {
throw new Error("Missing the required parameter 'ShamanCheckout' when calling shamanCheckout");
shamanCheckoutWithHttpInfo(shamanCheckout) {
let postBody = shamanCheckout;
// verify the required parameter 'shamanCheckout' is set
if (shamanCheckout === undefined || shamanCheckout === null) {
throw new Error("Missing the required parameter 'shamanCheckout' when calling shamanCheckout");
}
let pathParams = {
@ -74,11 +74,11 @@ export default class ShamanApi {
/**
* Create a directory, and symlink the required files into it. The files must all have been uploaded to Shaman before calling this endpoint.
* @param {module:model/ShamanCheckout} ShamanCheckout Set of files to check out.
* @param {module:model/ShamanCheckout} shamanCheckout Set of files to check out.
* @return {Promise} a {@link https://www.promisejs.org/|Promise}, with data of type {@link module:model/ShamanCheckoutResult}
*/
shamanCheckout(ShamanCheckout) {
return this.shamanCheckoutWithHttpInfo(ShamanCheckout)
shamanCheckout(shamanCheckout) {
return this.shamanCheckoutWithHttpInfo(shamanCheckout)
.then(function(response_and_data) {
return response_and_data.data;
});
@ -87,14 +87,14 @@ export default class ShamanApi {
/**
* Checks a Shaman Requirements file, and reports which files are unknown.
* @param {module:model/ShamanRequirementsRequest} ShamanRequirementsRequest Set of files to check
* @param {module:model/ShamanRequirementsRequest} shamanRequirementsRequest Set of files to check
* @return {Promise} a {@link https://www.promisejs.org/|Promise}, with an object containing data of type {@link module:model/ShamanRequirementsResponse} and HTTP response
*/
shamanCheckoutRequirementsWithHttpInfo(ShamanRequirementsRequest) {
let postBody = ShamanRequirementsRequest;
// verify the required parameter 'ShamanRequirementsRequest' is set
if (ShamanRequirementsRequest === undefined || ShamanRequirementsRequest === null) {
throw new Error("Missing the required parameter 'ShamanRequirementsRequest' when calling shamanCheckoutRequirements");
shamanCheckoutRequirementsWithHttpInfo(shamanRequirementsRequest) {
let postBody = shamanRequirementsRequest;
// verify the required parameter 'shamanRequirementsRequest' is set
if (shamanRequirementsRequest === undefined || shamanRequirementsRequest === null) {
throw new Error("Missing the required parameter 'shamanRequirementsRequest' when calling shamanCheckoutRequirements");
}
let pathParams = {
@ -119,11 +119,11 @@ export default class ShamanApi {
/**
* Checks a Shaman Requirements file, and reports which files are unknown.
* @param {module:model/ShamanRequirementsRequest} ShamanRequirementsRequest Set of files to check
* @param {module:model/ShamanRequirementsRequest} shamanRequirementsRequest Set of files to check
* @return {Promise} a {@link https://www.promisejs.org/|Promise}, with data of type {@link module:model/ShamanRequirementsResponse}
*/
shamanCheckoutRequirements(ShamanRequirementsRequest) {
return this.shamanCheckoutRequirementsWithHttpInfo(ShamanRequirementsRequest)
shamanCheckoutRequirements(shamanRequirementsRequest) {
return this.shamanCheckoutRequirementsWithHttpInfo(shamanRequirementsRequest)
.then(function(response_and_data) {
return response_and_data.data;
});
@ -136,8 +136,8 @@ export default class ShamanApi {
* @param {Number} filesize Size of the file in bytes.
* @param {File} body Contents of the file
* @param {Object} opts Optional parameters
* @param {Boolean} opts.X_Shaman_Can_Defer_Upload The client indicates that it can defer uploading this file. The \"208\" response will not only be returned when the file is already fully known to the Shaman server, but also when someone else is currently uploading this file.
* @param {String} opts.X_Shaman_Original_Filename The original filename. If sent along with the request, it will be included in the server logs, which can aid in debugging.
* @param {Boolean} opts.xShamanCanDeferUpload The client indicates that it can defer uploading this file. The \"208\" response will not only be returned when the file is already fully known to the Shaman server, but also when someone else is currently uploading this file.
* @param {String} opts.xShamanOriginalFilename The original filename. If sent along with the request, it will be included in the server logs, which can aid in debugging.
* @return {Promise} a {@link https://www.promisejs.org/|Promise}, with an object containing HTTP response
*/
shamanFileStoreWithHttpInfo(checksum, filesize, body, opts) {
@ -163,8 +163,8 @@ export default class ShamanApi {
let queryParams = {
};
let headerParams = {
'X-Shaman-Can-Defer-Upload': opts['X_Shaman_Can_Defer_Upload'],
'X-Shaman-Original-Filename': opts['X_Shaman_Original_Filename']
'X-Shaman-Can-Defer-Upload': opts['xShamanCanDeferUpload'],
'X-Shaman-Original-Filename': opts['xShamanOriginalFilename']
};
let formParams = {
};
@ -186,8 +186,8 @@ export default class ShamanApi {
* @param {Number} filesize Size of the file in bytes.
* @param {File} body Contents of the file
* @param {Object} opts Optional parameters
* @param {Boolean} opts.X_Shaman_Can_Defer_Upload The client indicates that it can defer uploading this file. The \"208\" response will not only be returned when the file is already fully known to the Shaman server, but also when someone else is currently uploading this file.
* @param {String} opts.X_Shaman_Original_Filename The original filename. If sent along with the request, it will be included in the server logs, which can aid in debugging.
* @param {Boolean} opts.xShamanCanDeferUpload The client indicates that it can defer uploading this file. The \"208\" response will not only be returned when the file is already fully known to the Shaman server, but also when someone else is currently uploading this file.
* @param {String} opts.xShamanOriginalFilename The original filename. If sent along with the request, it will be included in the server logs, which can aid in debugging.
* @return {Promise} a {@link https://www.promisejs.org/|Promise}
*/
shamanFileStore(checksum, filesize, body, opts) {

View File

@ -45,14 +45,14 @@ export default class WorkerApi {
/**
* Register a new worker
* @param {module:model/WorkerRegistration} WorkerRegistration Worker to register
* @param {module:model/WorkerRegistration} workerRegistration Worker to register
* @return {Promise} a {@link https://www.promisejs.org/|Promise}, with an object containing data of type {@link module:model/RegisteredWorker} and HTTP response
*/
registerWorkerWithHttpInfo(WorkerRegistration) {
let postBody = WorkerRegistration;
// verify the required parameter 'WorkerRegistration' is set
if (WorkerRegistration === undefined || WorkerRegistration === null) {
throw new Error("Missing the required parameter 'WorkerRegistration' when calling registerWorker");
registerWorkerWithHttpInfo(workerRegistration) {
let postBody = workerRegistration;
// verify the required parameter 'workerRegistration' is set
if (workerRegistration === undefined || workerRegistration === null) {
throw new Error("Missing the required parameter 'workerRegistration' when calling registerWorker");
}
let pathParams = {
@ -77,11 +77,11 @@ export default class WorkerApi {
/**
* Register a new worker
* @param {module:model/WorkerRegistration} WorkerRegistration Worker to register
* @param {module:model/WorkerRegistration} workerRegistration Worker to register
* @return {Promise} a {@link https://www.promisejs.org/|Promise}, with data of type {@link module:model/RegisteredWorker}
*/
registerWorker(WorkerRegistration) {
return this.registerWorkerWithHttpInfo(WorkerRegistration)
registerWorker(workerRegistration) {
return this.registerWorkerWithHttpInfo(workerRegistration)
.then(function(response_and_data) {
return response_and_data.data;
});
@ -168,14 +168,14 @@ export default class WorkerApi {
/**
* Authenticate & sign in the worker.
* @param {module:model/WorkerSignOn} WorkerSignOn Worker metadata
* @param {module:model/WorkerSignOn} workerSignOn Worker metadata
* @return {Promise} a {@link https://www.promisejs.org/|Promise}, with an object containing data of type {@link module:model/WorkerStateChange} and HTTP response
*/
signOnWithHttpInfo(WorkerSignOn) {
let postBody = WorkerSignOn;
// verify the required parameter 'WorkerSignOn' is set
if (WorkerSignOn === undefined || WorkerSignOn === null) {
throw new Error("Missing the required parameter 'WorkerSignOn' when calling signOn");
signOnWithHttpInfo(workerSignOn) {
let postBody = workerSignOn;
// verify the required parameter 'workerSignOn' is set
if (workerSignOn === undefined || workerSignOn === null) {
throw new Error("Missing the required parameter 'workerSignOn' when calling signOn");
}
let pathParams = {
@ -200,11 +200,11 @@ export default class WorkerApi {
/**
* Authenticate & sign in the worker.
* @param {module:model/WorkerSignOn} WorkerSignOn Worker metadata
* @param {module:model/WorkerSignOn} workerSignOn Worker metadata
* @return {Promise} a {@link https://www.promisejs.org/|Promise}, with data of type {@link module:model/WorkerStateChange}
*/
signOn(WorkerSignOn) {
return this.signOnWithHttpInfo(WorkerSignOn)
signOn(workerSignOn) {
return this.signOnWithHttpInfo(workerSignOn)
.then(function(response_and_data) {
return response_and_data.data;
});
@ -213,23 +213,23 @@ export default class WorkerApi {
/**
* Update the task, typically to indicate progress, completion, or failure.
* @param {String} task_id
* @param {module:model/TaskUpdate} TaskUpdate Task update information
* @param {String} taskId
* @param {module:model/TaskUpdate} taskUpdate Task update information
* @return {Promise} a {@link https://www.promisejs.org/|Promise}, with an object containing HTTP response
*/
taskUpdateWithHttpInfo(task_id, TaskUpdate) {
let postBody = TaskUpdate;
// verify the required parameter 'task_id' is set
if (task_id === undefined || task_id === null) {
throw new Error("Missing the required parameter 'task_id' when calling taskUpdate");
taskUpdateWithHttpInfo(taskId, taskUpdate) {
let postBody = taskUpdate;
// verify the required parameter 'taskId' is set
if (taskId === undefined || taskId === null) {
throw new Error("Missing the required parameter 'taskId' when calling taskUpdate");
}
// verify the required parameter 'TaskUpdate' is set
if (TaskUpdate === undefined || TaskUpdate === null) {
throw new Error("Missing the required parameter 'TaskUpdate' when calling taskUpdate");
// verify the required parameter 'taskUpdate' is set
if (taskUpdate === undefined || taskUpdate === null) {
throw new Error("Missing the required parameter 'taskUpdate' when calling taskUpdate");
}
let pathParams = {
'task_id': task_id
'task_id': taskId
};
let queryParams = {
};
@ -251,12 +251,12 @@ export default class WorkerApi {
/**
* Update the task, typically to indicate progress, completion, or failure.
* @param {String} task_id
* @param {module:model/TaskUpdate} TaskUpdate Task update information
* @param {String} taskId
* @param {module:model/TaskUpdate} taskUpdate Task update information
* @return {Promise} a {@link https://www.promisejs.org/|Promise}
*/
taskUpdate(task_id, TaskUpdate) {
return this.taskUpdateWithHttpInfo(task_id, TaskUpdate)
taskUpdate(taskId, taskUpdate) {
return this.taskUpdateWithHttpInfo(taskId, taskUpdate)
.then(function(response_and_data) {
return response_and_data.data;
});
@ -302,14 +302,14 @@ export default class WorkerApi {
/**
* Worker changed state. This could be as acknowledgement of a Manager-requested state change, or in response to worker-local signals.
* @param {module:model/WorkerStateChanged} WorkerStateChanged New worker state
* @param {module:model/WorkerStateChanged} workerStateChanged New worker state
* @return {Promise} a {@link https://www.promisejs.org/|Promise}, with an object containing HTTP response
*/
workerStateChangedWithHttpInfo(WorkerStateChanged) {
let postBody = WorkerStateChanged;
// verify the required parameter 'WorkerStateChanged' is set
if (WorkerStateChanged === undefined || WorkerStateChanged === null) {
throw new Error("Missing the required parameter 'WorkerStateChanged' when calling workerStateChanged");
workerStateChangedWithHttpInfo(workerStateChanged) {
let postBody = workerStateChanged;
// verify the required parameter 'workerStateChanged' is set
if (workerStateChanged === undefined || workerStateChanged === null) {
throw new Error("Missing the required parameter 'workerStateChanged' when calling workerStateChanged");
}
let pathParams = {
@ -334,11 +334,11 @@ export default class WorkerApi {
/**
* Worker changed state. This could be as acknowledgement of a Manager-requested state change, or in response to worker-local signals.
* @param {module:model/WorkerStateChanged} WorkerStateChanged New worker state
* @param {module:model/WorkerStateChanged} workerStateChanged New worker state
* @return {Promise} a {@link https://www.promisejs.org/|Promise}
*/
workerStateChanged(WorkerStateChanged) {
return this.workerStateChangedWithHttpInfo(WorkerStateChanged)
workerStateChanged(workerStateChanged) {
return this.workerStateChangedWithHttpInfo(workerStateChanged)
.then(function(response_and_data) {
return response_and_data.data;
});

View File

@ -30,14 +30,14 @@ class AssignedTask {
* @param name {String}
* @param status {module:model/TaskStatus}
* @param priority {Number}
* @param job_priority {Number}
* @param job_type {String}
* @param task_type {String}
* @param jobPriority {Number}
* @param jobType {String}
* @param taskType {String}
* @param commands {Array.<module:model/Command>}
*/
constructor(uuid, job, name, status, priority, job_priority, job_type, task_type, commands) {
constructor(uuid, job, name, status, priority, jobPriority, jobType, taskType, commands) {
AssignedTask.initialize(this, uuid, job, name, status, priority, job_priority, job_type, task_type, commands);
AssignedTask.initialize(this, uuid, job, name, status, priority, jobPriority, jobType, taskType, commands);
}
/**
@ -45,15 +45,15 @@ class AssignedTask {
* This method is used by the constructors of any subclasses, in order to implement multiple inheritance (mix-ins).
* Only for internal use.
*/
static initialize(obj, uuid, job, name, status, priority, job_priority, job_type, task_type, commands) {
static initialize(obj, uuid, job, name, status, priority, jobPriority, jobType, taskType, commands) {
obj['uuid'] = uuid;
obj['job'] = job;
obj['name'] = name;
obj['status'] = status;
obj['priority'] = priority;
obj['job_priority'] = job_priority;
obj['job_type'] = job_type;
obj['task_type'] = task_type;
obj['job_priority'] = jobPriority;
obj['job_type'] = jobType;
obj['task_type'] = taskType;
obj['commands'] = commands;
}

View File

@ -24,11 +24,11 @@ class AvailableJobTypes {
* Constructs a new <code>AvailableJobTypes</code>.
* List of job types supported by this Manager.
* @alias module:model/AvailableJobTypes
* @param job_types {Array.<module:model/AvailableJobType>}
* @param jobTypes {Array.<module:model/AvailableJobType>}
*/
constructor(job_types) {
constructor(jobTypes) {
AvailableJobTypes.initialize(this, job_types);
AvailableJobTypes.initialize(this, jobTypes);
}
/**
@ -36,8 +36,8 @@ class AvailableJobTypes {
* This method is used by the constructors of any subclasses, in order to implement multiple inheritance (mix-ins).
* Only for internal use.
*/
static initialize(obj, job_types) {
obj['job_types'] = job_types;
static initialize(obj, jobTypes) {
obj['job_types'] = jobTypes;
}
/**

View File

@ -28,13 +28,13 @@ class RegisteredWorker {
* @param address {String}
* @param status {module:model/WorkerStatus}
* @param platform {String}
* @param last_activity {String}
* @param lastActivity {String}
* @param software {String}
* @param supported_task_types {Array.<String>}
* @param supportedTaskTypes {Array.<String>}
*/
constructor(uuid, nickname, address, status, platform, last_activity, software, supported_task_types) {
constructor(uuid, nickname, address, status, platform, lastActivity, software, supportedTaskTypes) {
RegisteredWorker.initialize(this, uuid, nickname, address, status, platform, last_activity, software, supported_task_types);
RegisteredWorker.initialize(this, uuid, nickname, address, status, platform, lastActivity, software, supportedTaskTypes);
}
/**
@ -42,15 +42,15 @@ class RegisteredWorker {
* This method is used by the constructors of any subclasses, in order to implement multiple inheritance (mix-ins).
* Only for internal use.
*/
static initialize(obj, uuid, nickname, address, status, platform, last_activity, software, supported_task_types) {
static initialize(obj, uuid, nickname, address, status, platform, lastActivity, software, supportedTaskTypes) {
obj['uuid'] = uuid;
obj['nickname'] = nickname;
obj['address'] = address;
obj['status'] = status;
obj['platform'] = platform;
obj['last_activity'] = last_activity;
obj['last_activity'] = lastActivity;
obj['software'] = software;
obj['supported_task_types'] = supported_task_types;
obj['supported_task_types'] = supportedTaskTypes;
}
/**

View File

@ -24,12 +24,12 @@ class WorkerRegistration {
* @alias module:model/WorkerRegistration
* @param secret {String}
* @param platform {String}
* @param supported_task_types {Array.<String>}
* @param supportedTaskTypes {Array.<String>}
* @param nickname {String}
*/
constructor(secret, platform, supported_task_types, nickname) {
constructor(secret, platform, supportedTaskTypes, nickname) {
WorkerRegistration.initialize(this, secret, platform, supported_task_types, nickname);
WorkerRegistration.initialize(this, secret, platform, supportedTaskTypes, nickname);
}
/**
@ -37,10 +37,10 @@ class WorkerRegistration {
* This method is used by the constructors of any subclasses, in order to implement multiple inheritance (mix-ins).
* Only for internal use.
*/
static initialize(obj, secret, platform, supported_task_types, nickname) {
static initialize(obj, secret, platform, supportedTaskTypes, nickname) {
obj['secret'] = secret;
obj['platform'] = platform;
obj['supported_task_types'] = supported_task_types;
obj['supported_task_types'] = supportedTaskTypes;
obj['nickname'] = nickname;
}

View File

@ -23,12 +23,12 @@ class WorkerSignOn {
* Constructs a new <code>WorkerSignOn</code>.
* @alias module:model/WorkerSignOn
* @param nickname {String}
* @param supported_task_types {Array.<String>}
* @param software_version {String}
* @param supportedTaskTypes {Array.<String>}
* @param softwareVersion {String}
*/
constructor(nickname, supported_task_types, software_version) {
constructor(nickname, supportedTaskTypes, softwareVersion) {
WorkerSignOn.initialize(this, nickname, supported_task_types, software_version);
WorkerSignOn.initialize(this, nickname, supportedTaskTypes, softwareVersion);
}
/**
@ -36,10 +36,10 @@ class WorkerSignOn {
* This method is used by the constructors of any subclasses, in order to implement multiple inheritance (mix-ins).
* Only for internal use.
*/
static initialize(obj, nickname, supported_task_types, software_version) {
static initialize(obj, nickname, supportedTaskTypes, softwareVersion) {
obj['nickname'] = nickname;
obj['supported_task_types'] = supported_task_types;
obj['software_version'] = software_version;
obj['supported_task_types'] = supportedTaskTypes;
obj['software_version'] = softwareVersion;
}
/**

View File

@ -23,11 +23,11 @@ class WorkerStateChange {
/**
* Constructs a new <code>WorkerStateChange</code>.
* @alias module:model/WorkerStateChange
* @param status_requested {module:model/WorkerStatus}
* @param statusRequested {module:model/WorkerStatus}
*/
constructor(status_requested) {
constructor(statusRequested) {
WorkerStateChange.initialize(this, status_requested);
WorkerStateChange.initialize(this, statusRequested);
}
/**
@ -35,8 +35,8 @@ class WorkerStateChange {
* This method is used by the constructors of any subclasses, in order to implement multiple inheritance (mix-ins).
* Only for internal use.
*/
static initialize(obj, status_requested) {
obj['status_requested'] = status_requested;
static initialize(obj, statusRequested) {
obj['status_requested'] = statusRequested;
}
/**

View File

@ -0,0 +1,23 @@
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import('../views/AboutView.vue')
}
]
})
export default router

View File

@ -1,4 +1,5 @@
let url = new URL(window.location);
let url = new URL(window.location.href);
url.port = "8080";
const flamencoAPIURL = url.href;
@ -13,4 +14,9 @@ const URLs = {
console.log("Flamenco API:", URLs.api);
console.log("Websocket :", URLs.ws);
export default URLs;
export function ws() {
return URLs.ws;
}
export function api() {
return URLs.api;
}

View File

@ -0,0 +1,15 @@
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>
<style>
@media (min-width: 1024px) {
.about {
min-height: 100vh;
display: flex;
align-items: center;
}
}
</style>

View File

@ -0,0 +1,9 @@
<script setup>
import TheWelcome from '@/components/TheWelcome.vue'
</script>
<template>
<main>
<TheWelcome />
</main>
</template>

14
web/app/vite.config.js Normal file
View File

@ -0,0 +1,14 @@
import { fileURLToPath, URL } from 'url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})

View File

@ -1,12 +0,0 @@
/**
* @type {import('@vue/cli-service').ProjectOptions}
*/
module.exports = {
pages: {
index: {
entry: 'src/main.js',
title: 'Flamenco',
},
}
}

1344
web/app/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,33 +0,0 @@
{
"presets": [
"@babel/preset-env"
],
"plugins": [
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-syntax-import-meta",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-json-strings",
[
"@babel/plugin-proposal-decorators",
{
"legacy": true
}
],
"@babel/plugin-proposal-function-sent",
"@babel/plugin-proposal-export-namespace-from",
"@babel/plugin-proposal-numeric-separator",
"@babel/plugin-proposal-throw-expressions",
"@babel/plugin-proposal-export-default-from",
"@babel/plugin-proposal-logical-assignment-operators",
"@babel/plugin-proposal-optional-chaining",
[
"@babel/plugin-proposal-pipeline-operator",
{
"proposal": "minimal"
}
],
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-do-expressions",
"@babel/plugin-proposal-function-bind"
]
}

View File

@ -1,33 +0,0 @@
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directory
node_modules
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history

View File

@ -1,23 +0,0 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.
# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md

View File

@ -1,5 +0,0 @@
language: node_js
cache: npm
node_js:
- "6"
- "6.1"

View File

@ -1,186 +0,0 @@
# flamenco-manager
flamencoManager - JavaScript client for flamenco-manager
Render Farm manager API
This SDK is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 1.0.0
- Package version: 0.0.0
- Build package: org.openapitools.codegen.languages.JavascriptClientCodegen
For more information, please visit [https://flamenco.io/](https://flamenco.io/)
## Installation
### For [Node.js](https://nodejs.org/)
#### npm
To publish the library as a [npm](https://www.npmjs.com/), please follow the procedure in ["Publishing npm packages"](https://docs.npmjs.com/getting-started/publishing-npm-packages).
Then install it via:
```shell
npm install flamenco-manager --save
```
Finally, you need to build the module:
```shell
npm run build
```
##### Local development
To use the library locally without publishing to a remote npm registry, first install the dependencies by changing into the directory containing `package.json` (and this README). Let's call this `JAVASCRIPT_CLIENT_DIR`. Then run:
```shell
npm install
```
Next, [link](https://docs.npmjs.com/cli/link) it globally in npm with the following, also from `JAVASCRIPT_CLIENT_DIR`:
```shell
npm link
```
To use the link you just defined in your project, switch to the directory you want to use your flamenco-manager from, and run:
```shell
npm link /path/to/<JAVASCRIPT_CLIENT_DIR>
```
Finally, you need to build the module:
```shell
npm run build
```
#### git
If the library is hosted at a git repository, e.g.https://github.com/GIT_USER_ID/GIT_REPO_ID
then install it via:
```shell
npm install GIT_USER_ID/GIT_REPO_ID --save
```
### For browser
The library also works in the browser environment via npm and [browserify](http://browserify.org/). After following
the above steps with Node.js and installing browserify with `npm install -g browserify`,
perform the following (assuming *main.js* is your entry file):
```shell
browserify main.js > bundle.js
```
Then include *bundle.js* in the HTML pages.
### Webpack Configuration
Using Webpack you may encounter the following error: "Module not found: Error:
Cannot resolve module", most certainly you should disable AMD loader. Add/merge
the following section to your webpack config:
```javascript
module: {
rules: [
{
parser: {
amd: false
}
}
]
}
```
## Getting Started
Please follow the [installation](#installation) instruction and execute the following JS code:
```javascript
var flamencoManager = require('flamenco-manager');
var api = new flamencoManager.JobsApi()
var job_id = "job_id_example"; // {String}
api.fetchJob(job_id).then(function(data) {
console.log('API called successfully. Returned data: ' + data);
}, function(error) {
console.error(error);
});
```
## Documentation for API Endpoints
All URIs are relative to *http://localhost*
Class | Method | HTTP request | Description
------------ | ------------- | ------------- | -------------
*flamencoManager.JobsApi* | [**fetchJob**](docs/JobsApi.md#fetchJob) | **GET** /api/jobs/{job_id} | Fetch info about the job.
*flamencoManager.JobsApi* | [**getJobTypes**](docs/JobsApi.md#getJobTypes) | **GET** /api/jobs/types | Get list of job types and their parameters.
*flamencoManager.JobsApi* | [**queryJobs**](docs/JobsApi.md#queryJobs) | **POST** /api/jobs/query | Fetch list of jobs.
*flamencoManager.JobsApi* | [**submitJob**](docs/JobsApi.md#submitJob) | **POST** /api/jobs | Submit a new job for Flamenco Manager to execute.
*flamencoManager.MetaApi* | [**getConfiguration**](docs/MetaApi.md#getConfiguration) | **GET** /api/configuration | Get the configuration of this Manager.
*flamencoManager.MetaApi* | [**getVersion**](docs/MetaApi.md#getVersion) | **GET** /api/version | Get the Flamenco version of this Manager
*flamencoManager.ShamanApi* | [**shamanCheckout**](docs/ShamanApi.md#shamanCheckout) | **POST** /shaman/checkout/create | Create a directory, and symlink the required files into it. The files must all have been uploaded to Shaman before calling this endpoint.
*flamencoManager.ShamanApi* | [**shamanCheckoutRequirements**](docs/ShamanApi.md#shamanCheckoutRequirements) | **POST** /shaman/checkout/requirements | Checks a Shaman Requirements file, and reports which files are unknown.
*flamencoManager.ShamanApi* | [**shamanFileStore**](docs/ShamanApi.md#shamanFileStore) | **POST** /shaman/files/{checksum}/{filesize} | Store a new file on the Shaman server. Note that the Shaman server can forcibly close the HTTP connection when another client finishes uploading the exact same file, to prevent double uploads. The file&#39;s contents should be sent in the request body.
*flamencoManager.ShamanApi* | [**shamanFileStoreCheck**](docs/ShamanApi.md#shamanFileStoreCheck) | **GET** /shaman/files/{checksum}/{filesize} | Check the status of a file on the Shaman server.
*flamencoManager.WorkerApi* | [**registerWorker**](docs/WorkerApi.md#registerWorker) | **POST** /api/worker/register-worker | Register a new worker
*flamencoManager.WorkerApi* | [**scheduleTask**](docs/WorkerApi.md#scheduleTask) | **POST** /api/worker/task | Obtain a new task to execute
*flamencoManager.WorkerApi* | [**signOff**](docs/WorkerApi.md#signOff) | **POST** /api/worker/sign-off | Mark the worker as offline
*flamencoManager.WorkerApi* | [**signOn**](docs/WorkerApi.md#signOn) | **POST** /api/worker/sign-on | Authenticate &amp; sign in the worker.
*flamencoManager.WorkerApi* | [**taskUpdate**](docs/WorkerApi.md#taskUpdate) | **POST** /api/worker/task/{task_id} | Update the task, typically to indicate progress, completion, or failure.
*flamencoManager.WorkerApi* | [**workerState**](docs/WorkerApi.md#workerState) | **GET** /api/worker/state |
*flamencoManager.WorkerApi* | [**workerStateChanged**](docs/WorkerApi.md#workerStateChanged) | **POST** /api/worker/state-changed | Worker changed state. This could be as acknowledgement of a Manager-requested state change, or in response to worker-local signals.
## Documentation for Models
- [flamencoManager.AssignedTask](docs/AssignedTask.md)
- [flamencoManager.AvailableJobSetting](docs/AvailableJobSetting.md)
- [flamencoManager.AvailableJobSettingSubtype](docs/AvailableJobSettingSubtype.md)
- [flamencoManager.AvailableJobSettingType](docs/AvailableJobSettingType.md)
- [flamencoManager.AvailableJobType](docs/AvailableJobType.md)
- [flamencoManager.AvailableJobTypes](docs/AvailableJobTypes.md)
- [flamencoManager.Command](docs/Command.md)
- [flamencoManager.Error](docs/Error.md)
- [flamencoManager.FlamencoVersion](docs/FlamencoVersion.md)
- [flamencoManager.Job](docs/Job.md)
- [flamencoManager.JobAllOf](docs/JobAllOf.md)
- [flamencoManager.JobStatus](docs/JobStatus.md)
- [flamencoManager.JobUpdate](docs/JobUpdate.md)
- [flamencoManager.JobsQuery](docs/JobsQuery.md)
- [flamencoManager.JobsQueryResult](docs/JobsQueryResult.md)
- [flamencoManager.ManagerConfiguration](docs/ManagerConfiguration.md)
- [flamencoManager.RegisteredWorker](docs/RegisteredWorker.md)
- [flamencoManager.SecurityError](docs/SecurityError.md)
- [flamencoManager.ShamanCheckout](docs/ShamanCheckout.md)
- [flamencoManager.ShamanCheckoutResult](docs/ShamanCheckoutResult.md)
- [flamencoManager.ShamanFileSpec](docs/ShamanFileSpec.md)
- [flamencoManager.ShamanFileSpecWithStatus](docs/ShamanFileSpecWithStatus.md)
- [flamencoManager.ShamanFileStatus](docs/ShamanFileStatus.md)
- [flamencoManager.ShamanRequirementsRequest](docs/ShamanRequirementsRequest.md)
- [flamencoManager.ShamanRequirementsResponse](docs/ShamanRequirementsResponse.md)
- [flamencoManager.ShamanSingleFileStatus](docs/ShamanSingleFileStatus.md)
- [flamencoManager.SubmittedJob](docs/SubmittedJob.md)
- [flamencoManager.TaskStatus](docs/TaskStatus.md)
- [flamencoManager.TaskUpdate](docs/TaskUpdate.md)
- [flamencoManager.WorkerRegistration](docs/WorkerRegistration.md)
- [flamencoManager.WorkerSignOn](docs/WorkerSignOn.md)
- [flamencoManager.WorkerStateChange](docs/WorkerStateChange.md)
- [flamencoManager.WorkerStateChanged](docs/WorkerStateChanged.md)
- [flamencoManager.WorkerStatus](docs/WorkerStatus.md)
## Documentation for Authorization
### worker_auth
- **Type**: HTTP basic authentication

View File

@ -1,17 +0,0 @@
# flamencoManager.AssignedTask
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**uuid** | **String** | |
**job** | **String** | |
**name** | **String** | |
**status** | [**TaskStatus**](TaskStatus.md) | |
**priority** | **Number** | |
**job_priority** | **Number** | |
**job_type** | **String** | |
**task_type** | **String** | |
**commands** | [**[Command]**](Command.md) | |

View File

@ -1,19 +0,0 @@
# flamencoManager.AvailableJobSetting
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**key** | **String** | Identifier for the setting, must be unique within the job type. |
**type** | [**AvailableJobSettingType**](AvailableJobSettingType.md) | |
**subtype** | [**AvailableJobSettingSubtype**](AvailableJobSettingSubtype.md) | | [optional]
**choices** | **[String]** | When given, limit the valid values to these choices. Only usable with string type. | [optional]
**propargs** | **Object** | Any extra arguments to the bpy.props.SomeProperty() call used to create this property. | [optional]
**description** | **Object** | The description/tooltip shown in the user interface. | [optional]
**_default** | **Object** | The default value shown to the user when determining this setting. | [optional]
**_eval** | **String** | Python expression to be evaluated in order to determine the default value for this setting. | [optional]
**visible** | **Boolean** | Whether to show this setting in the UI of a job submitter (like a Blender add-on). Set to &#x60;false&#x60; when it is an internal setting that shouldn&#39;t be shown to end users. | [optional] [default to true]
**required** | **Boolean** | Whether to immediately reject a job definition, of this type, without this particular setting. | [optional] [default to false]
**editable** | **Boolean** | Whether to allow editing this setting after the job has been submitted. Would imply deleting all existing tasks for this job, and recompiling it. | [optional] [default to false]

View File

@ -1,14 +0,0 @@
# flamencoManager.AvailableJobSettingSubtype
## Enum
* `file_path` (value: `"file_path"`)
* `dir_path` (value: `"dir_path"`)
* `file_name` (value: `"file_name"`)
* `hashed_file_path` (value: `"hashed_file_path"`)

View File

@ -1,14 +0,0 @@
# flamencoManager.AvailableJobSettingType
## Enum
* `string` (value: `"string"`)
* `int32` (value: `"int32"`)
* `float` (value: `"float"`)
* `bool` (value: `"bool"`)

View File

@ -1,11 +0,0 @@
# flamencoManager.AvailableJobType
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | **String** | |
**label** | **String** | |
**settings** | [**[AvailableJobSetting]**](AvailableJobSetting.md) | |

View File

@ -1,9 +0,0 @@
# flamencoManager.AvailableJobTypes
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**job_types** | [**[AvailableJobType]**](AvailableJobType.md) | |

View File

@ -1,10 +0,0 @@
# flamencoManager.Command
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | **String** | |
**parameters** | **Object** | |

View File

@ -1,10 +0,0 @@
# flamencoManager.Error
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**code** | **Number** | HTTP status code of this response. Is included in the payload so that a single object represents all error information. Code 503 is used when the database is busy. The HTTP response will contain a &#39;Retry-After&#39; HTTP header that indicates after which time the request can be retried. Following the header is not mandatory, and it&#39;s up to the client to do something reasonable like exponential backoff. |
**message** | **String** | |

View File

@ -1,10 +0,0 @@
# flamencoManager.FlamencoVersion
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**version** | **String** | |
**name** | **String** | |

View File

@ -1,17 +0,0 @@
# flamencoManager.Job
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | **String** | |
**type** | **String** | |
**priority** | **Number** | | [default to 50]
**settings** | **{String: Object}** | | [optional]
**metadata** | **{String: String}** | Arbitrary metadata strings. More complex structures can be modeled by using &#x60;a.b.c&#x60; notation for the key. | [optional]
**id** | **String** | UUID of the Job |
**created** | **Date** | Creation timestamp |
**updated** | **Date** | Creation timestamp |
**status** | [**JobStatus**](JobStatus.md) | |

View File

@ -1,12 +0,0 @@
# flamencoManager.JobAllOf
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**id** | **String** | UUID of the Job |
**created** | **Date** | Creation timestamp |
**updated** | **Date** | Creation timestamp |
**status** | [**JobStatus**](JobStatus.md) | |

View File

@ -1,34 +0,0 @@
# flamencoManager.JobStatus
## Enum
* `active` (value: `"active"`)
* `canceled` (value: `"canceled"`)
* `completed` (value: `"completed"`)
* `construction-failed` (value: `"construction-failed"`)
* `failed` (value: `"failed"`)
* `paused` (value: `"paused"`)
* `queued` (value: `"queued"`)
* `archived` (value: `"archived"`)
* `archiving` (value: `"archiving"`)
* `cancel-requested` (value: `"cancel-requested"`)
* `fail-requested` (value: `"fail-requested"`)
* `requeued` (value: `"requeued"`)
* `under-construction` (value: `"under-construction"`)
* `waiting-for-files` (value: `"waiting-for-files"`)

View File

@ -1,13 +0,0 @@
# flamencoManager.JobUpdate
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**id** | **String** | UUID of the Job |
**name** | **String** | Name of the job | [optional]
**updated** | **Date** | Timestamp of last update |
**status** | [**JobStatus**](JobStatus.md) | |
**previous_status** | [**JobStatus**](JobStatus.md) | | [optional]

View File

@ -1,176 +0,0 @@
# flamencoManager.JobsApi
All URIs are relative to *http://localhost*
Method | HTTP request | Description
------------- | ------------- | -------------
[**fetchJob**](JobsApi.md#fetchJob) | **GET** /api/jobs/{job_id} | Fetch info about the job.
[**getJobTypes**](JobsApi.md#getJobTypes) | **GET** /api/jobs/types | Get list of job types and their parameters.
[**queryJobs**](JobsApi.md#queryJobs) | **POST** /api/jobs/query | Fetch list of jobs.
[**submitJob**](JobsApi.md#submitJob) | **POST** /api/jobs | Submit a new job for Flamenco Manager to execute.
## fetchJob
> Job fetchJob(job_id)
Fetch info about the job.
### Example
```javascript
import flamencoManager from 'flamenco-manager';
let apiInstance = new flamencoManager.JobsApi();
let job_id = "job_id_example"; // String |
apiInstance.fetchJob(job_id).then((data) => {
console.log('API called successfully. Returned data: ' + data);
}, (error) => {
console.error(error);
});
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**job_id** | **String**| |
### Return type
[**Job**](Job.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
## getJobTypes
> AvailableJobTypes getJobTypes()
Get list of job types and their parameters.
### Example
```javascript
import flamencoManager from 'flamenco-manager';
let apiInstance = new flamencoManager.JobsApi();
apiInstance.getJobTypes().then((data) => {
console.log('API called successfully. Returned data: ' + data);
}, (error) => {
console.error(error);
});
```
### Parameters
This endpoint does not need any parameter.
### Return type
[**AvailableJobTypes**](AvailableJobTypes.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
## queryJobs
> JobsQueryResult queryJobs(JobsQuery)
Fetch list of jobs.
### Example
```javascript
import flamencoManager from 'flamenco-manager';
let apiInstance = new flamencoManager.JobsApi();
let JobsQuery = new flamencoManager.JobsQuery(); // JobsQuery | Specification of which jobs to get.
apiInstance.queryJobs(JobsQuery).then((data) => {
console.log('API called successfully. Returned data: ' + data);
}, (error) => {
console.error(error);
});
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**JobsQuery** | [**JobsQuery**](JobsQuery.md)| Specification of which jobs to get. |
### Return type
[**JobsQueryResult**](JobsQueryResult.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
## submitJob
> Job submitJob(SubmittedJob)
Submit a new job for Flamenco Manager to execute.
### Example
```javascript
import flamencoManager from 'flamenco-manager';
let apiInstance = new flamencoManager.JobsApi();
let SubmittedJob = new flamencoManager.SubmittedJob(); // SubmittedJob | Job to submit
apiInstance.submitJob(SubmittedJob).then((data) => {
console.log('API called successfully. Returned data: ' + data);
}, (error) => {
console.error(error);
});
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**SubmittedJob** | [**SubmittedJob**](SubmittedJob.md)| Job to submit |
### Return type
[**Job**](Job.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json

View File

@ -1,14 +0,0 @@
# flamencoManager.JobsQuery
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**offset** | **Number** | | [optional]
**limit** | **Number** | | [optional]
**order_by** | **[String]** | | [optional]
**status_in** | [**[JobStatus]**](JobStatus.md) | Return only jobs with a status in this array. | [optional]
**metadata** | **{String: String}** | Filter by metadata, using &#x60;LIKE&#x60; notation. | [optional]
**settings** | **{String: Object}** | Filter by job settings, using &#x60;LIKE&#x60; notation. | [optional]

View File

@ -1,9 +0,0 @@
# flamencoManager.JobsQueryResult
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**jobs** | [**[Job]**](Job.md) | |

View File

@ -1,10 +0,0 @@
# flamencoManager.ManagerConfiguration
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**storageLocation** | **String** | Directory used for job file storage. |
**shamanEnabled** | **Boolean** | Whether the Shaman file transfer API is available. |

View File

@ -1,86 +0,0 @@
# flamencoManager.MetaApi
All URIs are relative to *http://localhost*
Method | HTTP request | Description
------------- | ------------- | -------------
[**getConfiguration**](MetaApi.md#getConfiguration) | **GET** /api/configuration | Get the configuration of this Manager.
[**getVersion**](MetaApi.md#getVersion) | **GET** /api/version | Get the Flamenco version of this Manager
## getConfiguration
> ManagerConfiguration getConfiguration()
Get the configuration of this Manager.
### Example
```javascript
import flamencoManager from 'flamenco-manager';
let apiInstance = new flamencoManager.MetaApi();
apiInstance.getConfiguration().then((data) => {
console.log('API called successfully. Returned data: ' + data);
}, (error) => {
console.error(error);
});
```
### Parameters
This endpoint does not need any parameter.
### Return type
[**ManagerConfiguration**](ManagerConfiguration.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
## getVersion
> FlamencoVersion getVersion()
Get the Flamenco version of this Manager
### Example
```javascript
import flamencoManager from 'flamenco-manager';
let apiInstance = new flamencoManager.MetaApi();
apiInstance.getVersion().then((data) => {
console.log('API called successfully. Returned data: ' + data);
}, (error) => {
console.error(error);
});
```
### Parameters
This endpoint does not need any parameter.
### Return type
[**FlamencoVersion**](FlamencoVersion.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json

View File

@ -1,16 +0,0 @@
# flamencoManager.RegisteredWorker
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**uuid** | **String** | |
**nickname** | **String** | |
**address** | **String** | |
**status** | [**WorkerStatus**](WorkerStatus.md) | |
**platform** | **String** | |
**last_activity** | **String** | |
**software** | **String** | |
**supported_task_types** | **[String]** | |

Some files were not shown because too many files have changed in this diff Show More