@fdm-monster/client-next 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.all-contributorsrc +57 -0
- package/.browserslistrc +4 -0
- package/.editorconfig +5 -0
- package/.env +1 -0
- package/.eslintrc-auto-import.json +73 -0
- package/.eslintrc.js +126 -0
- package/.github/FUNDING.yml +3 -0
- package/.github/workflows/release-client.yml +94 -0
- package/.github/workflows/vue-publish.yml +26 -0
- package/.prettierignore +15 -0
- package/.prettierrc.cjs +7 -0
- package/.whitesource +12 -0
- package/.yarn/releases/yarn-4.5.1.cjs +934 -0
- package/.yarnrc.yml +3 -0
- package/CODE_OF_CONDUCT.md +46 -0
- package/README.md +93 -0
- package/RELEASE_NOTES.MD +11 -0
- package/index.html +16 -0
- package/package.default.json +42 -0
- package/package.json +26 -0
- package/public/favicon.ico +0 -0
- package/public/img/DavidZwart.jpg +0 -0
- package/public/img/OIG.JYDC2RaWdz7g9.jpg +0 -0
- package/public/img/OIG.jpg +0 -0
- package/public/img/icons/android-chrome-192x192.png +0 -0
- package/public/img/icons/android-chrome-256x256.png +0 -0
- package/public/img/icons/android-chrome-384x384.png +0 -0
- package/public/img/icons/android-chrome-512x512.png +0 -0
- package/public/img/icons/favicon.svg +1 -0
- package/public/img/logo.png +0 -0
- package/public/img/logo.svg +1 -0
- package/public/img/manifest.webmanifest +33 -0
- package/public/img/octoprint-tentacle.svg +144 -0
- package/public/img/thumbail_unknown.jpg +0 -0
- package/public/img/vbanner.jpg +0 -0
- package/public/index.html +17 -0
- package/public/robots.txt +2 -0
- package/renovate.json +30 -0
- package/src/App.vue +60 -0
- package/src/AppLoader.vue +383 -0
- package/src/assets/adjectives.json +1468 -0
- package/src/assets/android-chrome-192x192.png +0 -0
- package/src/assets/logo.png +0 -0
- package/src/assets/logo.svg +6 -0
- package/src/assets/nouns.json +4309 -0
- package/src/auto-imports.d.ts +139 -0
- package/src/backend/app.service.ts +39 -0
- package/src/backend/auth.service.ts +56 -0
- package/src/backend/base.service.ts +57 -0
- package/src/backend/batch.service.ts +37 -0
- package/src/backend/camera-stream.service.ts +33 -0
- package/src/backend/custom-gcode.service.ts +11 -0
- package/src/backend/dto/octoprint-settings.dto.ts +168 -0
- package/src/backend/first-time-setup.service.ts +17 -0
- package/src/backend/floor.service.ts +84 -0
- package/src/backend/index.ts +4 -0
- package/src/backend/print-completions.service.ts +11 -0
- package/src/backend/printer-file.service.ts +91 -0
- package/src/backend/printer-group.service.ts +62 -0
- package/src/backend/printer-job.service.ts +20 -0
- package/src/backend/printer-settings.service.ts +28 -0
- package/src/backend/printers.service.ts +136 -0
- package/src/backend/server-private.service.ts +55 -0
- package/src/backend/server.api.ts +132 -0
- package/src/backend/settings.service.ts +85 -0
- package/src/backend/user.service.ts +51 -0
- package/src/components/AboutHelp/AboutView.vue +164 -0
- package/src/components/CameraGrid/CameraGridView.vue +111 -0
- package/src/components/FirstTimeSetup/FirstTimeSetupView.vue +354 -0
- package/src/components/Generic/Actions/PrinterConnectionAction.vue +56 -0
- package/src/components/Generic/Actions/PrinterCreateAction.vue +22 -0
- package/src/components/Generic/Actions/PrinterDeleteAction.vue +29 -0
- package/src/components/Generic/Actions/PrinterQuickStopAction.vue +35 -0
- package/src/components/Generic/Actions/PrinterSettingsAction.vue +35 -0
- package/src/components/Generic/Actions/PrinterUrlAction.vue +24 -0
- package/src/components/Generic/Actions/RefreshFilesAction.vue +50 -0
- package/src/components/Generic/Actions/SyncPrinterNameAction.vue +36 -0
- package/src/components/Generic/Dialogs/AddOrUpdateCameraStreamDialog.vue +131 -0
- package/src/components/Generic/Dialogs/AddOrUpdateFloorDialog.vue +141 -0
- package/src/components/Generic/Dialogs/AddOrUpdatePrinterDialog.vue +303 -0
- package/src/components/Generic/Dialogs/BaseDialog.vue +81 -0
- package/src/components/Generic/Dialogs/BatchJsonCreateDialog.vue +109 -0
- package/src/components/Generic/Dialogs/BatchReprintDialog.vue +190 -0
- package/src/components/Generic/Dialogs/PrinterChecksPanel.vue +37 -0
- package/src/components/Generic/Dialogs/PrinterControlDialog.vue +202 -0
- package/src/components/Generic/Dialogs/PrinterMaintenanceDialog.vue +130 -0
- package/src/components/Generic/Dialogs/YamlImportExportDialog.vue +186 -0
- package/src/components/Generic/Dialogs/dialog.constants.ts +19 -0
- package/src/components/Generic/FileExplorerSideNav.vue +734 -0
- package/src/components/Generic/Loaders/GridLoader.vue +68 -0
- package/src/components/Generic/NavigationDrawer.vue +69 -0
- package/src/components/Generic/PrintJobsMenu.vue +148 -0
- package/src/components/Generic/Snackbars/AppErrorSnackbar.vue +64 -0
- package/src/components/Generic/Snackbars/AppInfoSnackbar.vue +63 -0
- package/src/components/Generic/Snackbars/AppProgressSnackbar.vue +158 -0
- package/src/components/Generic/Vuetify/TooltipButton.vue +47 -0
- package/src/components/HelpOverlay/HelpOverlay.vue +57 -0
- package/src/components/Login/LoginForm.vue +206 -0
- package/src/components/Login/LoginView.spec.ts +64 -0
- package/src/components/Login/LoginView.vue +65 -0
- package/src/components/Login/Logo.vue +13 -0
- package/src/components/Login/PermissionDenied.vue +109 -0
- package/src/components/Login/RegistrationForm.vue +207 -0
- package/src/components/Login/RegistrationView.vue +17 -0
- package/src/components/Login/__snapshots__/LoginView.spec.ts.snap +1051 -0
- package/src/components/NotFound/NotFoundView.vue +39 -0
- package/src/components/PrintStatistics/PrintStatistics.vue +168 -0
- package/src/components/PrintStatistics/PrintStatisticsView.vue +15 -0
- package/src/components/PrinterGrid/HomeToolbar.vue +90 -0
- package/src/components/PrinterGrid/PrinterGrid.vue +164 -0
- package/src/components/PrinterGrid/PrinterGridTile.vue +438 -0
- package/src/components/PrinterGrid/PrinterGridView.vue +210 -0
- package/src/components/PrinterList/FileControlList.vue +40 -0
- package/src/components/PrinterList/PrinterDetails.vue +91 -0
- package/src/components/PrinterList/PrintersView.vue +492 -0
- package/src/components/Settings/AccountSettings.vue +163 -0
- package/src/components/Settings/DiagnosticsSettings.vue +137 -0
- package/src/components/Settings/EmergencyCommands.vue +265 -0
- package/src/components/Settings/FloorSettings.vue +276 -0
- package/src/components/Settings/GridSettings.vue +127 -0
- package/src/components/Settings/OctoPrintSettings.vue +188 -0
- package/src/components/Settings/ServerProtectionSettings.vue +370 -0
- package/src/components/Settings/SettingsView.vue +73 -0
- package/src/components/Settings/SoftwareUpgradeSettings.vue +297 -0
- package/src/components/Settings/UserManagementSettings.vue +257 -0
- package/src/components/TopBar.vue +147 -0
- package/src/components.d.ts +70 -0
- package/src/directives/file-upload.directive.ts +117 -0
- package/src/directives/printer-drop-position.directive.ts +92 -0
- package/src/env.d.ts +6 -0
- package/src/main.ts +76 -0
- package/src/models/batch/reprint.dto.ts +79 -0
- package/src/models/batch.model.ts +11 -0
- package/src/models/camera-streams/camera-stream.ts +19 -0
- package/src/models/floors/floor.model.ts +30 -0
- package/src/models/octoprint/connection-options.model.ts +8 -0
- package/src/models/plugins/firmware-updates/prusa-firmware-release.model.ts +57 -0
- package/src/models/print-completions/print-completions.model.ts +49 -0
- package/src/models/printers/crud/create-printer.model.ts +26 -0
- package/src/models/printers/file-upload-commands.model.ts +4 -0
- package/src/models/printers/gcode/gcode-analysis.model.ts +30 -0
- package/src/models/printers/printer-current-job.model.ts +90 -0
- package/src/models/printers/printer-file.model.ts +48 -0
- package/src/models/printers/printer.model.ts +18 -0
- package/src/models/server/client-releases.model.ts +27 -0
- package/src/models/server/export-yaml.model.ts +11 -0
- package/src/models/server/features.model.ts +37 -0
- package/src/models/server/github-rate-limit.model.ts +21 -0
- package/src/models/server/version.model.ts +14 -0
- package/src/models/settings/printer-file-clean-settings.model.ts +5 -0
- package/src/models/settings/server-settings.dto.ts +19 -0
- package/src/models/settings/settings.model.ts +57 -0
- package/src/models/socketio-messages/socketio-message.model.ts +53 -0
- package/src/models/uploads/queued-upload.model.ts +12 -0
- package/src/models/user.model.ts +15 -0
- package/src/plugins/README.md +3 -0
- package/src/plugins/index.ts +17 -0
- package/src/plugins/vuetify.ts +53 -0
- package/src/router/index.ts +192 -0
- package/src/router/route-names.ts +14 -0
- package/src/router/utils.ts +23 -0
- package/src/shared/alert.events.ts +14 -0
- package/src/shared/app.constants.ts +23 -0
- package/src/shared/auth.constants.ts +34 -0
- package/src/shared/dialog.composable.ts +41 -0
- package/src/shared/drag.constants.ts +19 -0
- package/src/shared/experimental.constants.ts +1 -0
- package/src/shared/http-client.ts +162 -0
- package/src/shared/noun-adjectives.data.ts +24 -0
- package/src/shared/printer-grid.constants.ts +5 -0
- package/src/shared/printer-state.constants.ts +194 -0
- package/src/shared/snackbar.composable.ts +66 -0
- package/src/shared/socketio.service.ts +104 -0
- package/src/store/auth.store.ts +255 -0
- package/src/store/connection.store.ts +66 -0
- package/src/store/dialog.store.ts +114 -0
- package/src/store/features.store.ts +57 -0
- package/src/store/floor.store.ts +173 -0
- package/src/store/grid.store.ts +10 -0
- package/src/store/index.ts +4 -0
- package/src/store/printer-state.store.ts +246 -0
- package/src/store/printer.store.ts +236 -0
- package/src/store/profile.store.ts +25 -0
- package/src/store/settings.store.ts +64 -0
- package/src/store/test-printer.store.ts +70 -0
- package/src/store/uploads.store.ts +75 -0
- package/src/styles/README.md +3 -0
- package/src/styles/settings.scss +10 -0
- package/src/types/global.d.ts +15 -0
- package/src/utils/array.utils.ts +15 -0
- package/src/utils/date.utils.ts +5 -0
- package/src/utils/download-file.util.ts +25 -0
- package/src/utils/error.utils.ts +3 -0
- package/src/utils/file-size.util.ts +11 -0
- package/src/utils/id.type.ts +1 -0
- package/src/utils/sentry.util.ts +8 -0
- package/src/utils/test.util.ts +30 -0
- package/src/utils/time.utils.ts +2 -0
- package/src/utils/uploads-state.utils.ts +58 -0
- package/src/utils/validation.utils.ts +14 -0
- package/src/vite-env.d.ts +7 -0
- package/test/setup-axios-mock.ts +15 -0
- package/tsconfig.json +47 -0
- package/tsconfig.node.json +9 -0
- package/vite.config.mts +106 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-card>
|
|
3
|
+
<v-card-title> About FDM Monster<strong> © </strong> </v-card-title>
|
|
4
|
+
<v-card-text>
|
|
5
|
+
The first prototype of FDM Monster<strong> © </strong> was created by
|
|
6
|
+
David Zwart in 2021 in collaboration with
|
|
7
|
+
<strong> <a href="https://mtb3d.com"> MTB3D </a> </strong>. This
|
|
8
|
+
open-source prototype proved a strong factor in process and logistics
|
|
9
|
+
optimization for a 3D Printing company with 100+ printers. Due to it's
|
|
10
|
+
success, we decided to keep it open-source and free!
|
|
11
|
+
</v-card-text>
|
|
12
|
+
<v-card-text>
|
|
13
|
+
The latest 3D Printing Farm server named FDM Monster has been tested for 2
|
|
14
|
+
years using a custom image for running 4 OctoPrint images on a Raspberry
|
|
15
|
+
Pi.
|
|
16
|
+
<br />
|
|
17
|
+
This version uses the famous
|
|
18
|
+
<a
|
|
19
|
+
href="https://nodejs.org/en"
|
|
20
|
+
target="_blank"
|
|
21
|
+
>
|
|
22
|
+
<strong> Node.js framework </strong>
|
|
23
|
+
</a>
|
|
24
|
+
together with Awilix and ExpressJS for its server, and
|
|
25
|
+
<a
|
|
26
|
+
href="https://vuejs.org/"
|
|
27
|
+
target="_blank"
|
|
28
|
+
>
|
|
29
|
+
<strong> Vue 2 </strong>
|
|
30
|
+
</a>
|
|
31
|
+
and
|
|
32
|
+
<a
|
|
33
|
+
href="https://next.vuetifyjs.com/"
|
|
34
|
+
target="_blank"
|
|
35
|
+
>
|
|
36
|
+
<strong> Vuetify 2 </strong>
|
|
37
|
+
</a>
|
|
38
|
+
to set a base for FDM Monster Client<strong> © </strong> - the webapp.
|
|
39
|
+
<br />
|
|
40
|
+
<br />
|
|
41
|
+
<strong> Your server's version is: {{ serverVersion }} </strong>
|
|
42
|
+
<br />
|
|
43
|
+
<strong> Your clients's version is: {{ version }} </strong>
|
|
44
|
+
<br />
|
|
45
|
+
<strong v-if="monsterPiVersion">
|
|
46
|
+
Your MonsterPi version is: {{ monsterPiVersion }}<br />
|
|
47
|
+
</strong>
|
|
48
|
+
<strong v-else> No MonsterPi distro detected. </strong>
|
|
49
|
+
<br />
|
|
50
|
+
<v-btn
|
|
51
|
+
class="mt-3"
|
|
52
|
+
variant="outlined"
|
|
53
|
+
to="/settings/software-upgrade"
|
|
54
|
+
>
|
|
55
|
+
Visit Upgrade Settings
|
|
56
|
+
</v-btn>
|
|
57
|
+
</v-card-text>
|
|
58
|
+
<v-card-title> Documentation </v-card-title>
|
|
59
|
+
<v-card-text>
|
|
60
|
+
<strong>
|
|
61
|
+
<v-btn
|
|
62
|
+
color="primary"
|
|
63
|
+
href="https://docs.fdm-monster.net"
|
|
64
|
+
style="color: white"
|
|
65
|
+
target="_blank"
|
|
66
|
+
>
|
|
67
|
+
<v-icon class="mr-2">menu_book</v-icon>
|
|
68
|
+
FDM Monster documentation site
|
|
69
|
+
</v-btn>
|
|
70
|
+
</strong>
|
|
71
|
+
<br />
|
|
72
|
+
</v-card-text>
|
|
73
|
+
|
|
74
|
+
<!-- Bug reports section -->
|
|
75
|
+
<v-card-title>
|
|
76
|
+
Bug reports
|
|
77
|
+
<v-icon>bug</v-icon>
|
|
78
|
+
</v-card-title>
|
|
79
|
+
<v-card-text>
|
|
80
|
+
Did you find a bug, or a feature that needs work? We would love to hear
|
|
81
|
+
about it! <br />
|
|
82
|
+
|
|
83
|
+
<strong> We have multiple ways to report it: </strong>
|
|
84
|
+
<h3>
|
|
85
|
+
<ul class="ml-5">
|
|
86
|
+
<li>Mail to davidzwa@gmail.com</li>
|
|
87
|
+
<li>
|
|
88
|
+
<a
|
|
89
|
+
href="https://discord.gg/mwA8uP8CMc"
|
|
90
|
+
style="color: white"
|
|
91
|
+
target="_blank"
|
|
92
|
+
>
|
|
93
|
+
Discord server
|
|
94
|
+
</a>
|
|
95
|
+
</li>
|
|
96
|
+
<li>
|
|
97
|
+
<strong>
|
|
98
|
+
<a
|
|
99
|
+
href="https://github.com/fdm-monster/fdm-monster/issues"
|
|
100
|
+
style="color: white"
|
|
101
|
+
target="_blank"
|
|
102
|
+
>
|
|
103
|
+
FDM Monster <strong> © </strong> Github Issues
|
|
104
|
+
</a>
|
|
105
|
+
</strong>
|
|
106
|
+
</li>
|
|
107
|
+
<li>
|
|
108
|
+
<a
|
|
109
|
+
href="https://fdm-monster.net"
|
|
110
|
+
style="color: white"
|
|
111
|
+
target="_blank"
|
|
112
|
+
>
|
|
113
|
+
Website
|
|
114
|
+
</a>
|
|
115
|
+
</li>
|
|
116
|
+
</ul>
|
|
117
|
+
</h3>
|
|
118
|
+
</v-card-text>
|
|
119
|
+
|
|
120
|
+
<v-card-title> About me </v-card-title>
|
|
121
|
+
<v-card-text>
|
|
122
|
+
<img
|
|
123
|
+
src="/img/DavidZwart.jpg"
|
|
124
|
+
width="150px"
|
|
125
|
+
/>
|
|
126
|
+
<h4 class="mt-2">
|
|
127
|
+
<a
|
|
128
|
+
href="https://www.linkedin.com/in/david-zwart-88514083/"
|
|
129
|
+
style="color: white"
|
|
130
|
+
target="_blank"
|
|
131
|
+
>
|
|
132
|
+
LinkedIn
|
|
133
|
+
</a>
|
|
134
|
+
|
|
135
|
+
<a
|
|
136
|
+
class="ml-2"
|
|
137
|
+
href="https://github.com/davidzwa"
|
|
138
|
+
style="color: white"
|
|
139
|
+
target="_blank"
|
|
140
|
+
>
|
|
141
|
+
Github Profile
|
|
142
|
+
</a>
|
|
143
|
+
</h4>
|
|
144
|
+
David Zwart MSc., post-graduate from the TU Delft (Embedded Systems),
|
|
145
|
+
author of FDM Monster<strong> © </strong>
|
|
146
|
+
</v-card-text>
|
|
147
|
+
</v-card>
|
|
148
|
+
</template>
|
|
149
|
+
|
|
150
|
+
<script lang="ts" setup>
|
|
151
|
+
import { onMounted, ref } from 'vue'
|
|
152
|
+
import { AppService } from '@/backend/app.service'
|
|
153
|
+
import { version as clientVersion } from '../../../package.json'
|
|
154
|
+
|
|
155
|
+
const serverVersion = ref('')
|
|
156
|
+
const monsterPiVersion = ref<string | null>('')
|
|
157
|
+
const version = ref(clientVersion)
|
|
158
|
+
|
|
159
|
+
onMounted(async () => {
|
|
160
|
+
const versionSpec = await AppService.getVersion()
|
|
161
|
+
serverVersion.value = versionSpec.version
|
|
162
|
+
monsterPiVersion.value = versionSpec.monsterPi
|
|
163
|
+
})
|
|
164
|
+
</script>
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<v-toolbar>
|
|
4
|
+
<v-toolbar-title class="mr-4"> Camera Overview </v-toolbar-title>
|
|
5
|
+
<v-btn
|
|
6
|
+
color="primary"
|
|
7
|
+
@click="addCamera()"
|
|
8
|
+
>
|
|
9
|
+
<v-icon class="mr-2">add</v-icon>
|
|
10
|
+
Add camera
|
|
11
|
+
</v-btn>
|
|
12
|
+
</v-toolbar>
|
|
13
|
+
<v-row class="ma-0">
|
|
14
|
+
<div
|
|
15
|
+
v-for="camera in query.data.value"
|
|
16
|
+
:key="camera.cameraStream.id"
|
|
17
|
+
class="ma-4"
|
|
18
|
+
style="border: 1px solid grey; margin: 0"
|
|
19
|
+
width="300"
|
|
20
|
+
>
|
|
21
|
+
<v-card
|
|
22
|
+
class="pb-2 pl-2 pr-2"
|
|
23
|
+
width="300"
|
|
24
|
+
>
|
|
25
|
+
<v-card-title>
|
|
26
|
+
<v-icon
|
|
27
|
+
v-if="camera.cameraStream.printerId"
|
|
28
|
+
class="mr-2"
|
|
29
|
+
size="small"
|
|
30
|
+
>
|
|
31
|
+
print
|
|
32
|
+
</v-icon>
|
|
33
|
+
<v-icon
|
|
34
|
+
v-else
|
|
35
|
+
class="mr-2"
|
|
36
|
+
size="small"
|
|
37
|
+
>
|
|
38
|
+
camera_alt
|
|
39
|
+
</v-icon>
|
|
40
|
+
{{ camera?.cameraStream.name ?? camera?.printer?.name ?? 'Camera' }}
|
|
41
|
+
</v-card-title>
|
|
42
|
+
<img
|
|
43
|
+
:src="camera.cameraStream?.streamURL"
|
|
44
|
+
width="100%"
|
|
45
|
+
/>
|
|
46
|
+
<br />
|
|
47
|
+
<v-btn
|
|
48
|
+
class="mr-1"
|
|
49
|
+
size="small"
|
|
50
|
+
@click="updateCamera(camera.cameraStream.id)"
|
|
51
|
+
>
|
|
52
|
+
<v-icon class="mr-2">edit</v-icon>
|
|
53
|
+
Update
|
|
54
|
+
</v-btn>
|
|
55
|
+
<v-btn
|
|
56
|
+
size="small"
|
|
57
|
+
@click="deleteCamera(camera.cameraStream.id)"
|
|
58
|
+
>
|
|
59
|
+
<v-icon class="mr-2">delete</v-icon>
|
|
60
|
+
Delete
|
|
61
|
+
</v-btn>
|
|
62
|
+
</v-card>
|
|
63
|
+
</div>
|
|
64
|
+
</v-row>
|
|
65
|
+
</div>
|
|
66
|
+
</template>
|
|
67
|
+
|
|
68
|
+
<script lang="ts" setup>
|
|
69
|
+
import { CameraStreamService } from '@/backend/camera-stream.service'
|
|
70
|
+
import { useDialog } from '@/shared/dialog.composable'
|
|
71
|
+
import { DialogName } from '@/components/Generic/Dialogs/dialog.constants'
|
|
72
|
+
import { useMutation, useQuery } from '@tanstack/vue-query'
|
|
73
|
+
import { CameraWithPrinter } from '@/models/camera-streams/camera-stream'
|
|
74
|
+
import { usePrinterStore } from '@/store/printer.store'
|
|
75
|
+
import { IdType } from '@/utils/id.type'
|
|
76
|
+
|
|
77
|
+
const printerStore = usePrinterStore()
|
|
78
|
+
const dialog = useDialog(DialogName.AddOrUpdateCameraDialog)
|
|
79
|
+
const camerasWithPrinter = async (): Promise<CameraWithPrinter[]> => {
|
|
80
|
+
const streams = await CameraStreamService.listCameraStreams()
|
|
81
|
+
return streams.map((cameraStream) => ({
|
|
82
|
+
printer: printerStore.printers.find(
|
|
83
|
+
(printer) => printer.id === cameraStream.printerId
|
|
84
|
+
),
|
|
85
|
+
cameraStream
|
|
86
|
+
})) as CameraWithPrinter[]
|
|
87
|
+
}
|
|
88
|
+
const query = useQuery({
|
|
89
|
+
queryKey: ['cameraStream'],
|
|
90
|
+
queryFn: camerasWithPrinter
|
|
91
|
+
})
|
|
92
|
+
const deleteMutation = useMutation({
|
|
93
|
+
mutationFn: (cameraId: IdType) =>
|
|
94
|
+
CameraStreamService.deleteCameraStream(cameraId),
|
|
95
|
+
onSuccess: () => query.refetch()
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
function addCamera() {
|
|
99
|
+
dialog.openDialog({ addOrUpdate: 'add' })
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function updateCamera(cameraId?: IdType) {
|
|
103
|
+
if (!cameraId) return
|
|
104
|
+
dialog.openDialog({ addOrUpdate: 'update', cameraId })
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function deleteCamera(cameraId?: IdType) {
|
|
108
|
+
if (!cameraId) return
|
|
109
|
+
deleteMutation.mutateAsync(cameraId)
|
|
110
|
+
}
|
|
111
|
+
</script>
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-container>
|
|
3
|
+
<img
|
|
4
|
+
alt="FDM Monster Background"
|
|
5
|
+
class="grid-bg-img align-content-center"
|
|
6
|
+
src="/img/logo.svg"
|
|
7
|
+
style="opacity: 0.08"
|
|
8
|
+
/>
|
|
9
|
+
<v-stepper
|
|
10
|
+
v-model="stepper"
|
|
11
|
+
class="bg-grey-darken-4"
|
|
12
|
+
>
|
|
13
|
+
<v-stepper-header>
|
|
14
|
+
<v-stepper-step
|
|
15
|
+
:complete="stepper > 1"
|
|
16
|
+
step="1"
|
|
17
|
+
>
|
|
18
|
+
Introduction
|
|
19
|
+
</v-stepper-step>
|
|
20
|
+
|
|
21
|
+
<v-divider />
|
|
22
|
+
|
|
23
|
+
<v-stepper-step
|
|
24
|
+
:complete="stepper > 2"
|
|
25
|
+
step="2"
|
|
26
|
+
>
|
|
27
|
+
Login and registration
|
|
28
|
+
</v-stepper-step>
|
|
29
|
+
|
|
30
|
+
<v-divider />
|
|
31
|
+
|
|
32
|
+
<v-stepper-step step="3"> Summary </v-stepper-step>
|
|
33
|
+
</v-stepper-header>
|
|
34
|
+
|
|
35
|
+
<v-stepper-items>
|
|
36
|
+
<v-stepper-content
|
|
37
|
+
class="align-content-center align-center text-center"
|
|
38
|
+
step="1"
|
|
39
|
+
>
|
|
40
|
+
<div class="align-content-center align-center text-center">
|
|
41
|
+
<img
|
|
42
|
+
class="rounded-pill ma-4"
|
|
43
|
+
src="/img/OIG.jpg"
|
|
44
|
+
style="opacity: 0.7"
|
|
45
|
+
width="400"
|
|
46
|
+
/>
|
|
47
|
+
/>
|
|
48
|
+
<h1>FDM Monster</h1>
|
|
49
|
+
<small> This server is still unconfigured. </small>
|
|
50
|
+
</div>
|
|
51
|
+
<v-btn
|
|
52
|
+
class="mt-14 mb-14"
|
|
53
|
+
color="primary"
|
|
54
|
+
@click="stepper = 2"
|
|
55
|
+
>
|
|
56
|
+
Start Setup
|
|
57
|
+
</v-btn>
|
|
58
|
+
|
|
59
|
+
<div class="mt-6 border_all">
|
|
60
|
+
<v-icon class="mr-6">question_mark</v-icon>
|
|
61
|
+
<small>
|
|
62
|
+
If you have questions at any point, reach out on
|
|
63
|
+
<a href="https://github.com/fdm-monster/fdm-monster/issues">
|
|
64
|
+
Github
|
|
65
|
+
</a>
|
|
66
|
+
or on <a href="https://discord.gg/mwA8uP8CMc"> Discord </a>.
|
|
67
|
+
</small>
|
|
68
|
+
</div>
|
|
69
|
+
</v-stepper-content>
|
|
70
|
+
<v-stepper-content
|
|
71
|
+
class="align-content-center align-center text-center"
|
|
72
|
+
step="2"
|
|
73
|
+
>
|
|
74
|
+
<h4><v-icon class="mr-2">settings</v-icon> Login</h4>
|
|
75
|
+
|
|
76
|
+
<v-form v-model="formValid">
|
|
77
|
+
<v-switch
|
|
78
|
+
v-model="formStep1.loginRequired"
|
|
79
|
+
class="mt-5"
|
|
80
|
+
>
|
|
81
|
+
<template #message>
|
|
82
|
+
<span class="d-flex flex-row align-center">
|
|
83
|
+
<v-icon
|
|
84
|
+
:color="formStep1.loginRequired ? 'success' : ''"
|
|
85
|
+
:disabled="!formStep1.loginRequired"
|
|
86
|
+
class="ml-3 mr-3"
|
|
87
|
+
>
|
|
88
|
+
check
|
|
89
|
+
</v-icon>
|
|
90
|
+
Login is required.
|
|
91
|
+
</span>
|
|
92
|
+
|
|
93
|
+
<span class="d-flex flex-row align-center">
|
|
94
|
+
<v-icon
|
|
95
|
+
:color="!formStep1.loginRequired ? 'error' : ''"
|
|
96
|
+
:disabled="formStep1.loginRequired"
|
|
97
|
+
class="ml-3 mr-3"
|
|
98
|
+
>
|
|
99
|
+
close
|
|
100
|
+
</v-icon>
|
|
101
|
+
No login is required. The admin role is assumed.
|
|
102
|
+
</span>
|
|
103
|
+
</template>
|
|
104
|
+
<template #label> Enable Login </template>
|
|
105
|
+
</v-switch>
|
|
106
|
+
|
|
107
|
+
<v-alert
|
|
108
|
+
v-if="!formStep1.loginRequired"
|
|
109
|
+
color="error-darken-4"
|
|
110
|
+
>
|
|
111
|
+
You might be exposing your FDM Monster server publicly. Please
|
|
112
|
+
take care evaluating the
|
|
113
|
+
<strong> Enable Login </strong> option.
|
|
114
|
+
</v-alert>
|
|
115
|
+
|
|
116
|
+
<v-switch
|
|
117
|
+
v-model="formStep1.registration"
|
|
118
|
+
class="mt-10 mb-10"
|
|
119
|
+
>
|
|
120
|
+
<template #message>
|
|
121
|
+
<span class="d-flex flex-row align-center">
|
|
122
|
+
<v-icon
|
|
123
|
+
:color="formStep1.registration ? 'success' : ''"
|
|
124
|
+
:disabled="!formStep1.registration"
|
|
125
|
+
class="ml-3 mr-3"
|
|
126
|
+
>
|
|
127
|
+
check
|
|
128
|
+
</v-icon>
|
|
129
|
+
Accounts can be registered with a guest role.
|
|
130
|
+
</span>
|
|
131
|
+
<span class="d-flex flex-row align-center">
|
|
132
|
+
<v-icon
|
|
133
|
+
:color="!formStep1.registration ? 'error' : ''"
|
|
134
|
+
:disabled="formStep1.registration"
|
|
135
|
+
class="ml-3 mr-3"
|
|
136
|
+
>
|
|
137
|
+
close
|
|
138
|
+
</v-icon>
|
|
139
|
+
No other accounts can be registered.
|
|
140
|
+
</span>
|
|
141
|
+
</template>
|
|
142
|
+
<template #label> Enable Registration </template>
|
|
143
|
+
</v-switch>
|
|
144
|
+
|
|
145
|
+
<v-divider />
|
|
146
|
+
|
|
147
|
+
<h4 class="mt-4">
|
|
148
|
+
<v-icon class="mr-2">shield</v-icon> Admin account
|
|
149
|
+
</h4>
|
|
150
|
+
|
|
151
|
+
<v-text-field
|
|
152
|
+
v-model="formStep2.rootUsername"
|
|
153
|
+
:rules="[(v) => !!v || 'Username is required']"
|
|
154
|
+
class="mt-5"
|
|
155
|
+
label="Username"
|
|
156
|
+
prepend-icon="person"
|
|
157
|
+
>
|
|
158
|
+
<template #prepend>
|
|
159
|
+
<v-icon>person</v-icon>
|
|
160
|
+
</template>
|
|
161
|
+
</v-text-field>
|
|
162
|
+
|
|
163
|
+
<v-text-field
|
|
164
|
+
v-model="formStep2.rootPassword"
|
|
165
|
+
type="password"
|
|
166
|
+
prepend-icon="lock"
|
|
167
|
+
:rules="[
|
|
168
|
+
(v) => !!v || 'Password is required',
|
|
169
|
+
(v) =>
|
|
170
|
+
(!!v && v?.length >= 8) ||
|
|
171
|
+
'Password must be of length 8 or greater'
|
|
172
|
+
]"
|
|
173
|
+
class="mt-5"
|
|
174
|
+
label="Password"
|
|
175
|
+
>
|
|
176
|
+
<template #prepend>
|
|
177
|
+
<v-icon>password</v-icon>
|
|
178
|
+
</template>
|
|
179
|
+
</v-text-field>
|
|
180
|
+
|
|
181
|
+
<v-text-field
|
|
182
|
+
v-model="formStep2.rootPassword2"
|
|
183
|
+
type="password"
|
|
184
|
+
prepend-icon="lock"
|
|
185
|
+
:rules="[
|
|
186
|
+
(v) => !!v || 'Repeated password is required',
|
|
187
|
+
(v) => v === formStep2.rootPassword || 'Passwords are not equal'
|
|
188
|
+
]"
|
|
189
|
+
class="mt-5"
|
|
190
|
+
label="Repeated Password"
|
|
191
|
+
>
|
|
192
|
+
<template #prepend>
|
|
193
|
+
<v-icon>password</v-icon>
|
|
194
|
+
</template>
|
|
195
|
+
</v-text-field>
|
|
196
|
+
</v-form>
|
|
197
|
+
|
|
198
|
+
<div class="mt-4">
|
|
199
|
+
<v-btn
|
|
200
|
+
class="mr-4"
|
|
201
|
+
@click="stepper = 1"
|
|
202
|
+
>
|
|
203
|
+
Back
|
|
204
|
+
</v-btn>
|
|
205
|
+
<v-btn
|
|
206
|
+
:disabled="!formValid"
|
|
207
|
+
color="primary"
|
|
208
|
+
@click="submitWizard()"
|
|
209
|
+
>
|
|
210
|
+
Verify & Submit
|
|
211
|
+
</v-btn>
|
|
212
|
+
</div>
|
|
213
|
+
|
|
214
|
+
<v-divider class="mt-4" />
|
|
215
|
+
|
|
216
|
+
<div class="mt-14">
|
|
217
|
+
<v-icon class="mr-6">question_mark</v-icon>
|
|
218
|
+
<small>
|
|
219
|
+
If you have questions at any point, reach out on
|
|
220
|
+
<a href="https://github.com/fdm-monster/fdm-monster/issues">
|
|
221
|
+
Github
|
|
222
|
+
</a>
|
|
223
|
+
or on <a href="https://discord.gg/mwA8uP8CMc"> Discord </a>.
|
|
224
|
+
</small>
|
|
225
|
+
</div>
|
|
226
|
+
</v-stepper-content>
|
|
227
|
+
<v-stepper-content
|
|
228
|
+
class="align-content-center align-center text-center"
|
|
229
|
+
step="3"
|
|
230
|
+
>
|
|
231
|
+
<div class="mb-5 mt-10">
|
|
232
|
+
<v-icon
|
|
233
|
+
size="100"
|
|
234
|
+
class="mr-5"
|
|
235
|
+
color="green circle"
|
|
236
|
+
>
|
|
237
|
+
check_circle
|
|
238
|
+
</v-icon>
|
|
239
|
+
Setup Completed
|
|
240
|
+
</div>
|
|
241
|
+
|
|
242
|
+
<br />
|
|
243
|
+
<v-btn
|
|
244
|
+
color="primary"
|
|
245
|
+
class="mr-4"
|
|
246
|
+
@click="continueNext()"
|
|
247
|
+
>
|
|
248
|
+
Let's continue
|
|
249
|
+
</v-btn>
|
|
250
|
+
|
|
251
|
+
<div class="mt-14">
|
|
252
|
+
<v-icon class="mr-6">question_mark</v-icon>
|
|
253
|
+
<small>
|
|
254
|
+
If you have questions at any point, reach out on
|
|
255
|
+
<a href="https://github.com/fdm-monster/fdm-monster/issues">
|
|
256
|
+
Github
|
|
257
|
+
</a>
|
|
258
|
+
or on <a href="https://discord.gg/mwA8uP8CMc"> Discord </a>.
|
|
259
|
+
</small>
|
|
260
|
+
</div>
|
|
261
|
+
</v-stepper-content>
|
|
262
|
+
</v-stepper-items>
|
|
263
|
+
</v-stepper>
|
|
264
|
+
</v-container>
|
|
265
|
+
</template>
|
|
266
|
+
<script lang="ts" setup>
|
|
267
|
+
import { onMounted, ref } from 'vue'
|
|
268
|
+
import { FirstTimeSetupService } from '@/backend/first-time-setup.service'
|
|
269
|
+
import { useSnackbar } from '@/shared/snackbar.composable'
|
|
270
|
+
import { useRouter } from 'vue-router'
|
|
271
|
+
import { useAuthStore } from '@/store/auth.store'
|
|
272
|
+
|
|
273
|
+
const router = useRouter()
|
|
274
|
+
const snackbar = useSnackbar()
|
|
275
|
+
const formValid = ref(false)
|
|
276
|
+
const authStore = useAuthStore()
|
|
277
|
+
const formStep1 = ref({
|
|
278
|
+
loginRequired: true,
|
|
279
|
+
registration: false
|
|
280
|
+
})
|
|
281
|
+
const formStep2 = ref({
|
|
282
|
+
rootUsername: 'admin',
|
|
283
|
+
rootPassword: '',
|
|
284
|
+
rootPassword2: ''
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
const stepper = ref(1)
|
|
288
|
+
|
|
289
|
+
onMounted(async () => {
|
|
290
|
+
await authStore.checkAuthenticationRequirements()
|
|
291
|
+
|
|
292
|
+
if (authStore.wizardState?.wizardCompleted) {
|
|
293
|
+
snackbar.info('Setup already completed.')
|
|
294
|
+
if (authStore.loginRequired) {
|
|
295
|
+
await router.push({ name: 'Login' })
|
|
296
|
+
} else {
|
|
297
|
+
await router.push({ name: 'Home' })
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
async function submitWizard() {
|
|
303
|
+
if (!formValid.value) {
|
|
304
|
+
snackbar.error('Please fill out all required fields.')
|
|
305
|
+
return
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const formValue = formStep1.value
|
|
309
|
+
const form2Value = formStep2.value
|
|
310
|
+
await FirstTimeSetupService.postFirstTimeSetup({
|
|
311
|
+
loginRequired: formValue.loginRequired,
|
|
312
|
+
registration: formValue.registration,
|
|
313
|
+
rootUsername: form2Value.rootUsername,
|
|
314
|
+
rootPassword: form2Value.rootPassword
|
|
315
|
+
})
|
|
316
|
+
snackbar.openInfoMessage({ title: 'Setup completed' })
|
|
317
|
+
stepper.value = 3
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
async function continueNext() {
|
|
321
|
+
await router.push({ name: 'Login' })
|
|
322
|
+
}
|
|
323
|
+
</script>
|
|
324
|
+
<style>
|
|
325
|
+
.typewriter h1 {
|
|
326
|
+
overflow: hidden; /* Ensures the content is not revealed until the animation */
|
|
327
|
+
border-right: 0.15em solid orange; /* The typwriter cursor */
|
|
328
|
+
white-space: nowrap; /* Keeps the content on a single line */
|
|
329
|
+
//margin: 0 auto; /* Gives that scrolling effect as the typing happens */
|
|
330
|
+
letter-spacing: 0.15em; /* Adjust as needed */
|
|
331
|
+
animation: typing 3.5s steps(40, end), blink-caret 0.75s step-end infinite;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/* The typing effect */
|
|
335
|
+
@keyframes typing {
|
|
336
|
+
from {
|
|
337
|
+
width: 0;
|
|
338
|
+
}
|
|
339
|
+
to {
|
|
340
|
+
width: 100%;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/* The typewriter cursor effect */
|
|
345
|
+
@keyframes blink-caret {
|
|
346
|
+
from,
|
|
347
|
+
to {
|
|
348
|
+
border-color: transparent;
|
|
349
|
+
}
|
|
350
|
+
50% {
|
|
351
|
+
border-color: orange;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
</style>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-badge
|
|
3
|
+
v-if="printer.enabled"
|
|
4
|
+
:color="isPrinterOperational() ? 'green' : 'red'"
|
|
5
|
+
bordered
|
|
6
|
+
class="ma-2"
|
|
7
|
+
overlap
|
|
8
|
+
>
|
|
9
|
+
<template #badge>
|
|
10
|
+
<v-icon v-if="isPrinterOperational()">check</v-icon>
|
|
11
|
+
<v-icon v-else>close</v-icon>
|
|
12
|
+
</template>
|
|
13
|
+
<v-btn
|
|
14
|
+
:disabled="isPrinterPrinting()"
|
|
15
|
+
fab
|
|
16
|
+
size="small"
|
|
17
|
+
@click.stop="togglePrinterConnection"
|
|
18
|
+
>
|
|
19
|
+
<v-icon>usb</v-icon>
|
|
20
|
+
</v-btn>
|
|
21
|
+
</v-badge>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<script lang="ts" setup>
|
|
25
|
+
import { defineProps } from 'vue'
|
|
26
|
+
import { PrinterDto } from '@/models/printers/printer.model'
|
|
27
|
+
import { PrintersService } from '@/backend'
|
|
28
|
+
import { usePrinterStateStore } from '@/store/printer-state.store'
|
|
29
|
+
|
|
30
|
+
const props = defineProps<{
|
|
31
|
+
printer: PrinterDto
|
|
32
|
+
}>()
|
|
33
|
+
|
|
34
|
+
const printerStateStore = usePrinterStateStore()
|
|
35
|
+
|
|
36
|
+
function isPrinterOperational() {
|
|
37
|
+
if (!props.printer.id) {
|
|
38
|
+
return false
|
|
39
|
+
}
|
|
40
|
+
return printerStateStore.isPrinterOperational(props.printer.id)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function isPrinterPrinting() {
|
|
44
|
+
if (!props.printer.id) {
|
|
45
|
+
return false
|
|
46
|
+
}
|
|
47
|
+
return printerStateStore.isPrinterPrinting(props.printer.id)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function togglePrinterConnection() {
|
|
51
|
+
if (isPrinterOperational()) {
|
|
52
|
+
return PrintersService.sendPrinterDisconnectCommand(props.printer.id)
|
|
53
|
+
}
|
|
54
|
+
await PrintersService.sendPrinterConnectCommand(props.printer.id)
|
|
55
|
+
}
|
|
56
|
+
</script>
|