WIP: 103268-job-task-progress #104185

Draft
Nitin-Rawat-1 wants to merge 19 commits from Nitin-Rawat-1/flamenco:103268-job-task-progress into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
43 changed files with 230 additions and 228 deletions
Showing only changes of commit 430b490407 - Show all commits

View File

@ -4,7 +4,7 @@ This file contains the history of changes to Flamenco. Only changes that might
be interesting for users are listed here, such as new features and fixes for
bugs in actually-released versions.
## 3.2 - in development
## 3.2 - released 2023-02-21
- When rendering EXR files, use Blender's preview JPEG files to generate the preview video ([43bc22f10fae](https://developer.blender.org/rF43bc22f10fae0fcaed6a4a3b3ace1be617193e21)).
- Fix issue where workers would switch immediately on a state change request, even if it was of the "after task is finished" kind.
@ -16,7 +16,10 @@ bugs in actually-released versions.
- Increase preview image file size from 10 MB to 25 MB. Even though the Worker can down-scale render output before sending to the Manager as preview, they could still be larger than the limit of 10 MB.
- Fix a crash of the Manager when using an invalid frame range (`1 10` for example, instead of `1-10` or `1,10`)
- Make it possible to delete jobs. The job and its tasks are removed from Flamenco, including last-rendered images and logs. The input files (i.e. the to-be-rendered blend files and their dependencies) will only be removed if [the Shaman system](https://flamenco.blender.org/usage/shared-storage/shaman/) was used AND if the job was submitted with Flamenco 3.2 or newer.
- Security updates of some dependencies:
- https://pkg.go.dev/vuln/GO-2022-1031
- https://pkg.go.dev/vuln/GO-2023-1571
- https://pkg.go.dev/vuln/GO-2023-1572
## 3.1 - released 2022-10-18

View File

@ -2,8 +2,8 @@ PKG := git.blender.org/flamenco
# To update the version number in all the relevant places, update the VERSION
# variable below and run `make update-version`.
VERSION := 3.2-beta
RELEASE_CYCLE := beta
VERSION := 3.2
RELEASE_CYCLE := release
# _GIT_DESCRIPTION_OR_TAG is either something like '16-123abc' (when we're 16
# commits since the last tag) or it's something like `v3.0-beta2` (when exactly

View File

@ -12,7 +12,7 @@ bl_info = {
"doc_url": "https://flamenco.blender.org/",
"category": "System",
"support": "COMMUNITY",
"warning": "This is version 3.2-beta of the add-on, which is not a stable release",
"warning": "",
}
from pathlib import Path

View File

@ -10,7 +10,7 @@
"""
__version__ = "3.2-beta"
__version__ = "3.2"
# import ApiClient
from flamenco.manager.api_client import ApiClient

View File

@ -76,7 +76,7 @@ class ApiClient(object):
self.default_headers[header_name] = header_value
self.cookie = cookie
# Set default User-Agent.
self.user_agent = 'Flamenco/3.2-beta (Blender add-on)'
self.user_agent = 'Flamenco/3.2 (Blender add-on)'
def __enter__(self):
return self

View File

@ -404,7 +404,7 @@ conf = flamenco.manager.Configuration(
"OS: {env}\n"\
"Python Version: {pyversion}\n"\
"Version of the API: 1.0.0\n"\
"SDK Package Version: 3.2-beta".\
"SDK Package Version: 3.2".\
format(env=sys.platform, pyversion=sys.version)
def get_host_settings(self):

View File

@ -4,7 +4,7 @@ Render Farm manager API
The `flamenco.manager` package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 1.0.0
- Package version: 3.2-beta
- Package version: 3.2
- Build package: org.openapitools.codegen.languages.PythonClientCodegen
For more information, please visit [https://flamenco.io/](https://flamenco.io/)

8
go.mod
View File

@ -25,8 +25,8 @@ require (
github.com/stretchr/testify v1.7.0
github.com/ziflex/lecho/v3 v3.1.0
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8
golang.org/x/net v0.5.0
golang.org/x/image v0.5.0
golang.org/x/net v0.7.0
gopkg.in/yaml.v2 v2.4.0
gorm.io/gorm v1.23.8
modernc.org/sqlite v1.17.3
@ -52,8 +52,8 @@ require (
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.1 // indirect
golang.org/x/mod v0.7.0 // indirect
golang.org/x/sys v0.4.0 // indirect
golang.org/x/text v0.6.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
golang.org/x/tools v0.5.1-0.20230117180257-8aba49bb5ea2 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect

23
go.sum
View File

@ -163,6 +163,7 @@ github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/ziflex/lecho/v3 v3.1.0 h1:65bSzSc0yw7EEhi44lMnkOI877ZzbE7tGDWfYCQXZwI=
github.com/ziflex/lecho/v3 v3.1.0/go.mod h1:dwQ6xCAKmSBHhwZ6XmiAiDptD7iklVkW7xQYGUncX0Q=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@ -175,11 +176,13 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e h1:1SzTfNOXwIS2oWiMF+6qu0OUDKb0dauo6MoDUQyu+yU=
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI=
golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@ -190,12 +193,14 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -222,17 +227,20 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -243,6 +251,7 @@ golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.5.1-0.20230117180257-8aba49bb5ea2 h1:v0FhRDmSCNH/0EurAT6T8KRY4aNuUhz6/WwBMxG+gvQ=
golang.org/x/tools v0.5.1-0.20230117180257-8aba49bb5ea2/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -24,6 +24,7 @@ var ApplicationGitHash = "set-during-build"
// that only supports strings.
var ReleaseCycle string = "set-during-build"
const releaseCycleReleaseCandidate = "rc"
const releaseCycleRelease = "release"
// FormattedApplicationInfo returns the application name & version as single string.
@ -39,9 +40,10 @@ func UserAgent() string {
// ExtendedVersion returns the application version, and includes the Git hash if
// this is not a release version. See `IsReleaseVersion`.
func ExtendedVersion() string {
if ReleaseCycle == releaseCycleRelease {
switch ReleaseCycle {
case releaseCycleRelease, releaseCycleReleaseCandidate:
return ApplicationVersion
default:
return fmt.Sprintf("%s-%s", ApplicationVersion, ApplicationGitHash)
}
return fmt.Sprintf("%s-%s", ApplicationVersion, ApplicationGitHash)
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 513 B

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

8
web/app/public/mkico.sh Executable file
View File

@ -0,0 +1,8 @@
#!/bin/bash
convert flamenco.png -bordercolor '#00000000' -border 0 \
\( -clone 0 -resize 16x16 \) \
\( -clone 0 -resize 32x32 \) \
\( -clone 0 -resize 48x48 \) \
\( -clone 0 -resize 64x64 \) \
-delete 0 -colors 256 favicon.ico

View File

@ -26,7 +26,7 @@
<script>
import * as API from '@/manager-api';
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
import { backendURL } from '@/urls';
import ApiSpinner from '@/components/ApiSpinner.vue'
@ -51,7 +51,7 @@ export default {
methods: {
// TODO: also call this when SocketIO reconnects.
fetchManagerInfo() {
const metaAPI = new API.MetaApi(apiClient);
const metaAPI = new API.MetaApi(getAPIClient());
metaAPI.getVersion().then((version) => {
this.flamencoName = version.name;
this.flamencoVersion = version.version;

View File

@ -17,7 +17,7 @@ const DEFAULT_FLAMENCO_NAME = "Flamenco";
const DEFAULT_FLAMENCO_VERSION = "unknown";
import ApiSpinner from '@/components/ApiSpinner.vue'
import { MetaApi } from "@/manager-api";
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
export default {
name: 'SetupAssistant',
@ -35,7 +35,7 @@ export default {
methods: {
// TODO: also call this when SocketIO reconnects.
fetchManagerInfo() {
const metaAPI = new MetaApi(apiClient);
const metaAPI = new MetaApi(getAPIClient());
metaAPI.getVersion().then((version) => {
this.flamencoName = version.name;
this.flamencoVersion = version.version;

39
web/app/src/api-client.js Normal file
View File

@ -0,0 +1,39 @@
import { ApiClient } from "@/manager-api";
import { CountingApiClient } from "@/stores/api-query-count";
import { api as apiURL } from '@/urls'
/**
* Scrub the custom User-Agent header from the API client, for those webbrowsers
* who do not want to have it set.
*
* It's actually scrubbed for all webbrowsers, as those privacy-first
* webbrowsers also make it hard to fingerprint which browser you're using (for
* good reason).
*
* @param {ApiClient} apiClient
*/
export function scrubAPIClient(apiClient) {
delete apiClient.defaultHeaders['User-Agent'];
}
/**
* @returns {ApiClient} Bare API client that is not connected to the UI in any way.
*/
export function newBareAPIClient() {
const apiClient = new ApiClient(apiURL());
scrubAPIClient(apiClient);
return apiClient;
}
let apiClient = null;
/**
* @returns {ApiClient} API client that updates the UI to show long-running queries.
*/
export function getAPIClient() {
if (apiClient == null) {
apiClient = new CountingApiClient(apiURL());
scrubAPIClient(apiClient);
}
return apiClient;
}

View File

@ -26,7 +26,7 @@
import { ref } from 'vue';
import { useNotifs } from '@/stores/notifications';
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
import { JobsApi, JobPriorityChange } from '@/manager-api';
const props = defineProps({
@ -45,7 +45,7 @@ const errorMessage = ref('');
// Methods
function updateJobPriority() {
const jobPriorityChange = new JobPriorityChange(priorityState.value);
const jobsAPI = new JobsApi(apiClient);
const jobsAPI = new JobsApi(getAPIClient());
return jobsAPI.setJobPriority(props.jobId, jobPriorityChange)
.then(() => {
notifs.add(`Updated job priority to ${priorityState.value}`)

View File

@ -3,7 +3,7 @@ import { onMounted, onUnmounted } from 'vue'
import { TabulatorFull as Tabulator } from 'tabulator-tables';
import { useTaskLog } from '@/stores/tasklog'
import { useTasks } from '@/stores/tasks'
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
import { JobsApi } from '@/manager-api';
const taskLog = useTaskLog();
@ -59,7 +59,7 @@ function _fetchLogTail(taskID) {
if (!taskID) return;
const jobsAPI = new JobsApi(apiClient);
const jobsAPI = new JobsApi(getAPIClient());
return jobsAPI.fetchTaskLogTail(taskID)
.then((logTail) => {
taskLog.addChunk(logTail);

View File

@ -26,7 +26,7 @@
</template>
<script setup>
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
import { JobsApi } from '@/manager-api';
import LinkWorker from '@/components/LinkWorker.vue';
import { watch, onMounted, inject, ref, nextTick } from 'vue'
@ -35,7 +35,7 @@ import { watch, onMounted, inject, ref, nextTick } from 'vue'
const props = defineProps(['jobID']);
const emit = defineEmits(['reshuffled'])
const jobsApi = new JobsApi(apiClient);
const jobsApi = new JobsApi(getAPIClient());
const isVisible = inject("isVisible");
const isFetching = ref(false);
const errorMsg = ref("");

View File

@ -18,7 +18,7 @@
<script>
import { useJobs } from '@/stores/jobs';
import { useNotifs } from '@/stores/notifications';
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
import { JobsApi } from '@/manager-api';
import { JobDeletionInfo } from '@/manager-api';
@ -31,7 +31,7 @@ export default {
data: () => ({
jobs: useJobs(),
notifs: useNotifs(),
jobsAPI: new JobsApi(apiClient),
jobsAPI: new JobsApi(getAPIClient()),
deleteInfo: null,
}),
@ -98,7 +98,6 @@ export default {
* @param { JobDeletionInfo } deleteInfo
*/
_showDeleteJobPopup(deleteInfo) {
console.log("deleteInfo", deleteInfo);
this.deleteInfo = deleteInfo;
},

View File

@ -39,7 +39,7 @@
<dd class="field-status-label" :class="'status-' + jobData.status">{{ jobData.status }}</dd>
<dt class="field-type" title="Type">Type</dt>
<dd>{{ jobType? jobType.label : jobData.type }}</dd>
<dd>{{ jobType ? jobType.label : jobData.type }}</dd>
<dt class="field-priority" title="Priority">Priority</dt>
<dd>
@ -76,7 +76,7 @@
<script>
import * as datetime from "@/datetime";
import * as API from '@/manager-api';
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
import LastRenderedImage from '@/components/jobs/LastRenderedImage.vue'
import Blocklist from './Blocklist.vue'
import TabItem from '@/components/TabItem.vue'
@ -103,7 +103,7 @@ export default {
datetime: datetime, // So that the template can access it.
copyElementText: copyElementText,
simpleSettings: null, // Object with filtered job settings, or null if there is no job.
jobsApi: new API.JobsApi(apiClient),
jobsApi: new API.JobsApi(getAPIClient()),
jobType: null, // API.AvailableJobType object for the current job type.
jobTypeSettings: null, // Mapping from setting key to its definition in the job type.
showAllSettings: false,

View File

@ -17,7 +17,7 @@ import { TabulatorFull as Tabulator } from 'tabulator-tables';
import * as datetime from "@/datetime";
import * as API from '@/manager-api'
import { indicator } from '@/statusindicator';
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
import { useJobs } from '@/stores/jobs';
import JobActionsBar from '@/components/jobs/JobActionsBar.vue'
@ -130,7 +130,7 @@ export default {
this.fetchAllJobs();
},
fetchAllJobs() {
const jobsApi = new API.JobsApi(apiClient);
const jobsApi = new API.JobsApi(getAPIClient());
const jobsQuery = {};
this.jobs.isJobless = false;
jobsApi.queryJobs(jobsQuery).then(this.onJobsFetched, function (error) {

View File

@ -9,7 +9,7 @@
import { reactive, ref, watch } from 'vue'
import { api } from '@/urls';
import { JobsApi, JobLastRenderedImageInfo, SocketIOLastRenderedUpdate } from '@/manager-api';
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
const props = defineProps([
/* The job UUID to show renders for, or some false-y value if renders from all
@ -27,7 +27,7 @@ const cssClasses = reactive({
'nothing-rendered-yet': true,
})
const jobsApi = new JobsApi(apiClient);
const jobsApi = new JobsApi(getAPIClient());
/**
* Fetches the last-rendered info for the given job, then updates the <img> tag for it.

View File

@ -73,7 +73,7 @@
import * as datetime from "@/datetime";
import { JobsApi } from '@/manager-api';
import { backendURL } from '@/urls';
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
import { useNotifs } from "@/stores/notifications";
import LinkWorker from '@/components/LinkWorker.vue';
import { copyElementText } from '@/clipboard';
@ -90,7 +90,7 @@ export default {
return {
datetime: datetime, // So that the template can access it.
copyElementText: copyElementText,
jobsApi: new JobsApi(apiClient),
jobsApi: new JobsApi(getAPIClient()),
notifs: useNotifs(),
};
},

View File

@ -17,7 +17,7 @@ import { TabulatorFull as Tabulator } from 'tabulator-tables';
import * as datetime from "@/datetime";
import * as API from '@/manager-api'
import { indicator } from '@/statusindicator';
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
import { useTasks } from '@/stores/tasks';
import TaskActionsBar from '@/components/jobs/TaskActionsBar.vue'
@ -132,7 +132,7 @@ export default {
return;
}
const jobsApi = new API.JobsApi(apiClient);
const jobsApi = new API.JobsApi(getAPIClient());
jobsApi.fetchJobTasks(this.jobID)
.then(this.onTasksFetched, function (error) {
// TODO: error handling.

View File

@ -6,11 +6,7 @@
</option>
<option v-for="(action, key) in WORKER_ACTIONS" :value="key">{{ action.label }}</option>
</select>
<button
:disabled="!canPerformAction"
class="btn"
@click.prevent="performWorkerAction"
>Apply</button>
<button :disabled="!canPerformAction" class="btn" @click.prevent="performWorkerAction">Apply</button>
</template>
<script setup>
@ -18,46 +14,46 @@ import { computed, ref } from 'vue'
import { useWorkers } from '@/stores/workers';
import { useNotifs } from '@/stores/notifications';
import { WorkerMgtApi, WorkerStatusChangeRequest } from '@/manager-api';
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
/* Freeze to prevent Vue.js from creating getters & setters all over this object.
* We don't need it to be tracked, as it won't be changed anyway. */
const WORKER_ACTIONS = Object.freeze({
offline_lazy: {
label: 'Shut Down (after task is finished)',
icon: '✝',
title: 'Shut down the worker after the current task finishes. The worker may automatically restart.',
target_status: 'offline',
lazy: true,
},
offline_immediate: {
label: 'Shut Down (immediately)',
icon: '✝!',
title: 'Immediately shut down the worker. It may automatically restart.',
target_status: 'offline',
lazy: false,
},
asleep_lazy: {
label: 'Send to Sleep (after task is finished)',
icon: '😴',
title: 'Let the worker sleep after finishing this task.',
target_status: 'asleep',
lazy: true,
},
asleep_immediate: {
label: 'Send to Sleep (immediately)',
icon: '😴!',
title: 'Let the worker sleep immediately.',
target_status: 'asleep',
lazy: false,
},
wakeup: {
label: 'Wake Up',
icon: '😃',
title: 'Wake the worker up. A sleeping worker can take a minute to respond.',
target_status: 'awake',
lazy: false,
},
offline_lazy: {
label: 'Shut Down (after task is finished)',
icon: '✝',
title: 'Shut down the worker after the current task finishes. The worker may automatically restart.',
target_status: 'offline',
lazy: true,
},
offline_immediate: {
label: 'Shut Down (immediately)',
icon: '✝!',
title: 'Immediately shut down the worker. It may automatically restart.',
target_status: 'offline',
lazy: false,
},
asleep_lazy: {
label: 'Send to Sleep (after task is finished)',
icon: '😴',
title: 'Let the worker sleep after finishing this task.',
target_status: 'asleep',
lazy: true,
},
asleep_immediate: {
label: 'Send to Sleep (immediately)',
icon: '😴!',
title: 'Let the worker sleep immediately.',
target_status: 'asleep',
lazy: false,
},
wakeup: {
label: 'Wake Up',
icon: '😃',
title: 'Wake the worker up. A sleeping worker can take a minute to respond.',
target_status: 'awake',
lazy: false,
},
});
const selectedAction = ref('');
@ -73,7 +69,7 @@ function performWorkerAction() {
return;
}
const api = new WorkerMgtApi(apiClient);
const api = new WorkerMgtApi(getAPIClient());
const action = WORKER_ACTIONS[selectedAction.value];
const statuschange = new WorkerStatusChangeRequest(action.target_status, action.lazy);
console.log("Requesting worker status change", statuschange);

View File

@ -123,7 +123,7 @@ import { useNotifs } from '@/stores/notifications'
import * as datetime from "@/datetime";
import { WorkerMgtApi, WorkerSleepSchedule } from '@/manager-api';
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
import { workerStatus } from "../../statusindicator";
import LinkWorkerTask from '@/components/LinkWorkerTask.vue';
import SwitchCheckbox from '@/components/SwitchCheckbox.vue';
@ -140,7 +140,7 @@ export default {
data() {
return {
datetime: datetime, // So that the template can access it.
api: new WorkerMgtApi(apiClient),
api: new WorkerMgtApi(getAPIClient()),
workerStatusHTML: "",
workerSleepSchedule: this.defaultWorkerSleepSchedule(),
isScheduleEditing: false,

View File

@ -19,7 +19,7 @@
import { TabulatorFull as Tabulator } from 'tabulator-tables';
import { WorkerMgtApi } from '@/manager-api'
import { indicator, workerStatus } from '@/statusindicator';
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
import { useWorkers } from '@/stores/workers';
import StatusFilterBar from '@/components/StatusFilterBar.vue'
@ -117,7 +117,7 @@ export default {
this.fetchAllWorkers();
},
fetchAllWorkers() {
const api = new WorkerMgtApi(apiClient);
const api = new WorkerMgtApi(getAPIClient());
api.fetchWorkers().then(this.onWorkersFetched, function (error) {
// TODO: error handling.
console.error(error);

View File

@ -7,7 +7,8 @@ import SetupAssistant from '@/SetupAssistant.vue'
import autoreload from '@/autoreloader'
import router from '@/router/index'
import setupAssistantRouter from '@/router/setup-assistant'
import { ApiClient, MetaApi } from "@/manager-api";
import { MetaApi } from "@/manager-api";
import { newBareAPIClient } from "@/api-client";
import * as urls from '@/urls'
// Ensure Tabulator can find `luxon`, which it needs for sorting by
@ -24,7 +25,6 @@ autoreload();
const pinia = createPinia()
function normalMode() {
console.log("Flamenco is starting in normal operation mode");
const app = createApp(App)
app.use(pinia)
app.use(router)
@ -42,7 +42,7 @@ function setupAssistantMode() {
/* This cannot use the client from '@/stores/api-query-count', as that would
* require Pinia, which is unavailable until the app is actually started. And to
* know which app to start, this API call needs to return data. */
const apiClient = new ApiClient(urls.api());;
const apiClient = newBareAPIClient();
const metaAPI = new MetaApi(apiClient);
metaAPI.getConfiguration()
.then((config) => {

View File

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

View File

@ -1,6 +1,5 @@
import { defineStore } from "pinia";
import { ApiClient } from "@/manager-api";
import * as urls from '@/urls'
/**
* Keep track of running API queries.
@ -42,5 +41,3 @@ export class CountingApiClient extends ApiClient {
});
}
}
export const apiClient = new CountingApiClient(urls.api());;

View File

@ -1,10 +1,10 @@
import { defineStore } from 'pinia'
import * as API from '@/manager-api';
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
const jobsAPI = new API.JobsApi(apiClient);
const jobsAPI = new API.JobsApi(getAPIClient());
// 'use' prefix is idiomatic for Pinia stores.
// See https://pinia.vuejs.org/core-concepts/

View File

@ -1,10 +1,10 @@
import { defineStore } from 'pinia'
import * as API from '@/manager-api';
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
const jobsAPI = new API.JobsApi(apiClient);
const jobsAPI = new API.JobsApi(getAPIClient());
// 'use' prefix is idiomatic for Pinia stores.
// See https://pinia.vuejs.org/core-concepts/

View File

@ -39,7 +39,7 @@ import { useJobs } from '@/stores/jobs';
import { useTasks } from '@/stores/tasks';
import { useNotifs } from '@/stores/notifications'
import { useTaskLog } from '@/stores/tasklog'
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
import FooterPopup from '@/components/footer/FooterPopup.vue'
import GetTheAddon from '@/components/GetTheAddon.vue'
@ -127,7 +127,7 @@ export default {
return;
}
const jobsAPI = new API.JobsApi(apiClient);
const jobsAPI = new API.JobsApi(getAPIClient());
jobsAPI.fetchTask(taskSummary.id)
.then((task) => {
this.tasks.setActiveTask(task);
@ -225,7 +225,7 @@ export default {
return;
}
const jobsAPI = new API.JobsApi(apiClient);
const jobsAPI = new API.JobsApi(getAPIClient());
return jobsAPI.fetchJob(jobID)
.then((job) => {
this.jobs.setActiveJob(job);
@ -254,7 +254,7 @@ export default {
return;
}
const jobsAPI = new API.JobsApi(apiClient);
const jobsAPI = new API.JobsApi(getAPIClient());
return jobsAPI.fetchTask(taskID)
.then((task) => {
this.tasks.setActiveTask(task);

View File

@ -2,38 +2,28 @@
<div class="setup-container">
<h1>Flamenco Setup Assistant</h1>
<ul class="progress">
<li
v-for="step in totalSetupSteps" :key="step"
@click="jumpToStep(step)"
:class="{
current: step == currentSetupStep,
done: step < overallSetupStep,
done_previously: (step < overallSetupStep && currentSetupStep > step),
done_and_current: step == currentSetupStep && (step < overallSetupStep || step == 1),
disabled: step > overallSetupStep,
}"
>
<li v-for="step in totalSetupSteps" :key="step" @click="jumpToStep(step)" :class="{
current: step == currentSetupStep,
done: step < overallSetupStep,
done_previously: (step < overallSetupStep && currentSetupStep > step),
done_and_current: step == currentSetupStep && (step < overallSetupStep || step == 1),
disabled: step > overallSetupStep,
}">
<span></span>
</li>
<div class="progress-bar"></div>
</ul>
<div class="setup-step step-welcome">
<step-item
v-show="currentSetupStep == 1"
@next-clicked="nextStep"
:is-next-clickable="true"
:is-back-visible="false"
title="Welcome!"
next-label="Let's go"
>
<step-item v-show="currentSetupStep == 1" @next-clicked="nextStep" :is-next-clickable="true"
:is-back-visible="false" title="Welcome!" next-label="Let's go">
<p>
This setup assistant will guide you through the initial configuration of Flamenco. You will be up
and running in a few minutes!
</p>
<p>Before we start, here is a quick overview of the Flamenco architecture.</p>
<img src="@/assets/architecture.png" alt="Flamenco architecture"/>
<img src="@/assets/architecture.png" alt="Flamenco architecture" />
<p>The illustration shows the key components and how they interact together:</p>
<ul>
@ -41,26 +31,24 @@
<strong>Manager</strong>: This application. It coordinates all the activity.
</li>
<li>
<strong>Worker</strong>: A workstation or dedicated rendering machine. It executes the tasks assigned by the Manager.
<strong>Worker</strong>: A workstation or dedicated rendering machine. It executes the tasks assigned by the
Manager.
</li>
<li>
<strong>Shared Storage</strong>: A location accessible by the Manager and the Workers, where the files to be rendered should be saved.
<strong>Shared Storage</strong>: A location accessible by the Manager and the Workers, where the files to be
rendered should be saved.
</li>
<li>
<strong>Blender Add-on</strong>: This is needed to connect to the Manager and submit a job from Blender.
</li>
</ul>
<p>More information is available on the online documentation at
<a href="https://flamenco.blender.org">flamenco.blender.org</a>.</p>
<a href="https://flamenco.blender.org">flamenco.blender.org</a>.
</p>
</step-item>
<step-item
v-show="currentSetupStep == 2"
@next-clicked="nextStepAfterCheckSharedStoragePath"
@back-clicked="prevStep"
:is-next-clickable="sharedStoragePath.length > 0"
title="Shared Storage"
>
<step-item v-show="currentSetupStep == 2" @next-clicked="nextStepAfterCheckSharedStoragePath"
@back-clicked="prevStep" :is-next-clickable="sharedStoragePath.length > 0" title="Shared Storage">
<p>Specify a path (or drive) where you want to store your Flamenco data.</p>
<p>
The location of the shared storage should be accessible by Flamenco Manager and by the Workers.
@ -79,37 +67,26 @@
<a href="https://flamenco.blender.org/usage/shared-storage/">Learn more</a>.
</p>
<input
v-model="sharedStoragePath"
@keyup.enter="nextStepAfterCheckSharedStoragePath"
type="text"
placeholder="Path to shared storage"
:class="{
<input v-model="sharedStoragePath" @keyup.enter="nextStepAfterCheckSharedStoragePath" type="text"
placeholder="Path to shared storage" :class="{
'is-invalid': (sharedStorageCheckResult != null) && !sharedStorageCheckResult.is_usable
}"
>
<p v-if="sharedStorageCheckResult != null"
:class="{
'check-ok': sharedStorageCheckResult.is_usable,
'check-failed': !sharedStorageCheckResult.is_usable
}">
<p v-if="sharedStorageCheckResult != null" :class="{
'check-ok': sharedStorageCheckResult.is_usable,
'check-failed': !sharedStorageCheckResult.is_usable
}">
{{ sharedStorageCheckResult.cause }}
</p>
</step-item>
<step-item
v-show="currentSetupStep == 3"
@next-clicked="nextStepAfterCheckBlenderExePath"
@back-clicked="prevStep"
:is-next-clickable="selectedBlender != null || customBlenderExe != (null || '')"
title="Blender"
>
<step-item v-show="currentSetupStep == 3" @next-clicked="nextStepAfterCheckBlenderExePath" @back-clicked="prevStep"
:is-next-clickable="selectedBlender != null || customBlenderExe != (null || '')" title="Blender">
<div v-if="isBlenderExeFinding" class="is-in-progress">Looking for Blender installs...</div>
<p v-if="autoFoundBlenders.length === 0">
Provide a path to a Blender executable accessible by all Workers.
<br/><br/>
<br /><br />
If your rendering setup features operating systems different from the one you are currently using,
you can manually set up the other paths later.
</p>
@ -119,23 +96,16 @@
<fieldset v-if="autoFoundBlenders.length >= 1">
<label v-if="autoFoundBlenderPathEnvvar" for="blender-path_envvar">
<div>
<input
v-model="selectedBlender"
:value="autoFoundBlenderPathEnvvar"
id="blender-path_envvar"
name="blender"
<input v-model="selectedBlender" :value="autoFoundBlenderPathEnvvar" id="blender-path_envvar" name="blender"
type="radio">
{{ sourceLabels[autoFoundBlenderPathEnvvar.source] }}
{{ sourceLabels[autoFoundBlenderPathEnvvar.source] }}
</div>
<div class="setup-path-command">
<span class="path">
{{autoFoundBlenderPathEnvvar.path}}
{{ autoFoundBlenderPathEnvvar.path }}
</span>
<span
aria-label="Console output when running with --version"
class="command-preview"
data-microtip-position="top"
role="tooltip">
<span aria-label="Console output when running with --version" class="command-preview"
data-microtip-position="top" role="tooltip">
{{ autoFoundBlenderPathEnvvar.cause }}
</span>
</div>
@ -143,23 +113,16 @@
<label v-if="autoFoundBlenderFileAssociation" for="blender-file_association">
<div>
<input
v-model="selectedBlender"
:value="autoFoundBlenderFileAssociation"
id="blender-file_association"
name="blender"
type="radio">
{{ sourceLabels[autoFoundBlenderFileAssociation.source] }}
<input v-model="selectedBlender" :value="autoFoundBlenderFileAssociation" id="blender-file_association"
name="blender" type="radio">
{{ sourceLabels[autoFoundBlenderFileAssociation.source] }}
</div>
<div class="setup-path-command">
<span class="path">
{{autoFoundBlenderFileAssociation.path}}
{{ autoFoundBlenderFileAssociation.path }}
</span>
<span
aria-label="Console output when running with --version"
class="command-preview"
data-microtip-position="top"
role="tooltip">
<span aria-label="Console output when running with --version" class="command-preview"
data-microtip-position="top" role="tooltip">
{{ autoFoundBlenderFileAssociation.cause }}
</span>
</div>
@ -167,24 +130,15 @@
<label for="blender-input_path">
<div>
<input
type="radio"
v-model="selectedBlender"
name="blender"
:value="blenderFromInputPath"
id="blender-input_path"
>
<input type="radio" v-model="selectedBlender" name="blender" :value="blenderFromInputPath"
id="blender-input_path">
{{ sourceLabels['input_path'] }}
</div>
<div>
<input
v-model="customBlenderExe"
@keyup.enter="nextStepAfterCheckBlenderExePath"
<input v-model="customBlenderExe" @keyup.enter="nextStepAfterCheckBlenderExePath"
@focus="selectedBlender = null"
:class="{'is-invalid': blenderExeCheckResult != null && !blenderExeCheckResult.is_usable}"
type="text"
placeholder="Path to Blender"
>
:class="{ 'is-invalid': blenderExeCheckResult != null && !blenderExeCheckResult.is_usable }" type="text"
placeholder="Path to Blender">
<p v-if="isBlenderExeChecking" class="is-in-progress">Checking...</p>
<p v-if="blenderExeCheckResult != null && !blenderExeCheckResult.is_usable" class="check-failed">
{{ blenderExeCheckResult.cause }}</p>
@ -193,13 +147,9 @@
</fieldset>
<div v-if="autoFoundBlenders.length === 0">
<input
v-model="customBlenderExe"
@keyup.enter="nextStepAfterCheckBlenderExePath"
:class="{'is-invalid': blenderExeCheckResult != null && !blenderExeCheckResult.is_usable}"
type="text"
placeholder="Path to Blender executable"
>
<input v-model="customBlenderExe" @keyup.enter="nextStepAfterCheckBlenderExePath"
:class="{ 'is-invalid': blenderExeCheckResult != null && !blenderExeCheckResult.is_usable }" type="text"
placeholder="Path to Blender executable">
<p v-if="isBlenderExeChecking" class="is-in-progress">Checking...</p>
<p v-if="blenderExeCheckResult != null && !blenderExeCheckResult.is_usable" class="check-failed">
@ -207,14 +157,8 @@
</div>
</step-item>
<step-item
v-show="currentSetupStep == 4"
@next-clicked="confirmSetupAssistant"
@back-clicked="prevStep"
next-label="Confirm"
title="Review"
:is-next-clickable="setupConfirmIsClickable"
>
<step-item v-show="currentSetupStep == 4" @next-clicked="confirmSetupAssistant" @back-clicked="prevStep"
next-label="Confirm" title="Review" :is-next-clickable="setupConfirmIsClickable">
<div v-if="isConfigComplete">
<p>This is the configuration that will be used by Flamenco:</p>
<dl>
@ -253,7 +197,7 @@ import NotificationBar from '@/components/footer/NotificationBar.vue'
import UpdateListener from '@/components/UpdateListener.vue'
import StepItem from '@/components/steps/StepItem.vue';
import { MetaApi, PathCheckInput, SetupAssistantConfig } from "@/manager-api";
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
export default {
name: 'SetupAssistantView',
@ -265,7 +209,7 @@ export default {
data: () => ({
sharedStoragePath: "",
sharedStorageCheckResult: null, // api.PathCheckResult
metaAPI: new MetaApi(apiClient),
metaAPI: new MetaApi(getAPIClient()),
allBlenders: [], // combination of autoFoundBlenders and blenderExeCheckResult.
@ -458,7 +402,6 @@ export default {
}
</script>
<style>
.step-welcome ul {
padding-left: var(--spacer-xl);
margin-bottom: var(--spacer-xl);
@ -517,7 +460,8 @@ export default {
}
.progress-bar {
--width-each-segment: calc(100% / calc(v-bind('totalSetupSteps') - 1)); /* Substract 1 because the first step has no progress. */
--width-each-segment: calc(100% / calc(v-bind('totalSetupSteps') - 1));
/* Substract 1 because the first step has no progress. */
--progress-bar-width-at-current-step: calc(var(--width-each-segment) * calc(v-bind('currentSetupStep') - 1));
position: absolute;

View File

@ -7,8 +7,7 @@
</div>
<footer class="app-footer">
<notification-bar />
<update-listener ref="updateListener" mainSubscription="allWorkers"
@workerUpdate="onSIOWorkerUpdate"
<update-listener ref="updateListener" mainSubscription="allWorkers" @workerUpdate="onSIOWorkerUpdate"
@sioReconnected="onSIOReconnected" @sioDisconnected="onSIODisconnected" />
</footer>
</template>
@ -17,6 +16,7 @@
.col-workers-list {
grid-area: col-1;
}
.col-workers-2 {
grid-area: col-2;
}
@ -26,7 +26,7 @@
import { WorkerMgtApi } from '@/manager-api';
import { useNotifs } from '@/stores/notifications'
import { useWorkers } from '@/stores/workers';
import { apiClient } from '@/stores/api-query-count';
import { getAPIClient } from "@/api-client";
import NotificationBar from '@/components/footer/NotificationBar.vue'
import UpdateListener from '@/components/UpdateListener.vue'
@ -45,7 +45,7 @@ export default {
data: () => ({
workers: useWorkers(),
notifs: useNotifs(),
api: new WorkerMgtApi(apiClient),
api: new WorkerMgtApi(getAPIClient()),
}),
mounted() {
window.workersView = this;

View File

@ -10,11 +10,16 @@ people.
## Steps to release a new version of Flamenco
Replace `${VERSION}` with the actual version number.
1. Update `CHANGELOG.md` and mark the to-be-released version as released today.
2. Update `Makefile` and change the `VERSION` and `RELEASE_CYCLE` variables.
3. Run `make update-version`
4. Commit & tag with the commands shown in the 2nd step.
5. Run `make release-package`
6. Check that the files in `dist/` are there and have a non-zero size.
7. Run `make publish-release-packages` to upload the packages to the website.
8. Run `make project-website` to generate and publish the new website.
2. Update `web/project-website/data/flamenco.yaml` for the new version.
3. Update `Makefile` and change the `VERSION` and `RELEASE_CYCLE` variables.
4. `make update-version`
5. `git commit -m "Bump version to ${VERSION}"`
6. `git tag v${VERSION}`
7. `make release-package`
8. Check that the files in `dist/` are there and have a non-zero size.
9. `make publish-release-packages` to upload the packages to the website.
10. `make project-website` to generate and publish the new website.
11. `git push && git push --tags`

View File

@ -1 +1 @@
latestVersion: "3.1"
latestVersion: "3.2"