diff --git a/.env b/.env index f256c63d..a8331286 100644 --- a/.env +++ b/.env @@ -1,2 +1,6 @@ +VUE_APP_JIRA_CLIENT_ID=3tPI6y3UgOxjUUVd2ELL3mhZr6cGAatt +VUE_APP_JIRA_CLIENT_SECRET=ATOAHCxhe5I4NKjvZo_hnzLSS6N038CmfyUsdnoXHCI0e8el_dY_xrFmMFJVHMAfa14d8502F3BF VUE_APP_I18N_LOCALE=en VUE_APP_I18N_FALLBACK_LOCALE=en + +VUE_APP_SERVER_PORT=64064 diff --git a/README.md b/README.md index b3bab0c9..a38445a0 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ If you have an idea about how we can better meet that goal, please let us know b If you looking to contribute - please checkout the [contributing guidelines](docs/CONTRIBUTING.md). -If you're just looking to take it for a spin, check out the pre-built [packages](https://github.com/dacoaster/yattie/releases) and find the one built for your platform. Can't find the platform you're looking for? Let us know you'd like a new one supported at the [feature requests](https://features.yattie.ai) page! +If you're just looking to take it for a spin, check out the pre-built [packages](https://yatt.ai/downloads) and find the one built for your platform. Can't find the platform you're looking for? Let us know you'd like a new one supported at the [feature requests](https://features.yattie.ai) page! ### Installation @@ -88,7 +88,7 @@ TODO - This section could use some love (and screenshots!) ## Usage -TODO - This section could use some love (and screenshots!) +Check out our [docs](https://docs.yattie.ai). ## Roadmap diff --git a/package.json b/package.json index 310009d0..83dc7296 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,7 @@ { "name": "yattie", - "version": "0.4.3", + "version": "0.5.0", "private": true, - "main": "background.js", "engines": { "npm": ">=8.0.0 <9.0.0", "node": ">=16.0.0 <17.0.0" @@ -15,32 +14,41 @@ "license": "GPLv3", "scripts": { "serve": "vue-cli-service serve", + "build": "vue-cli-service electron:build", "test:unit": "vue-cli-service test:unit", "lint": "vue-cli-service lint", "dev": "vue-cli-service electron:serve", - "build": "vue-cli-service electron:build", "i18n:report": "vue-cli-service i18n:report --src \"./src/**/*.?(js|vue)\" --locales \"./src/locales/**/*.json\"", "postinstall": "electron-builder install-app-deps", "postuninstall": "electron-builder install-app-deps", "publish": "vue-cli-service electron:build -p always" }, + "main": "background.js", "dependencies": { "@fortawesome/fontawesome-free": "^6.2.1", "@johmun/vue-tags-input": "^2.1.0", "@peepi/vuetify-tiptap": "^1.2.3", - "tui-image-editor": "^3.15.3", "adm-zip": "^0.5.9", + "axios": "^1.2.1", + "body-parser": "^1.20.1", + "child_process": "^1.0.2", + "client-oauth2": "^4.3.3", "core-js": "^3.8.3", + "cors": "^2.8.5", "d3": "^5.14.2", "dayjs": "^1.11.5", "detect-file-type": "^0.2.8", + "express": "^4.18.2", "extract-zip": "^2.0.1", "ffmpeg-static": "^5.1.0", "ffprobe-static": "^3.1.0", "fluent-ffmpeg": "^2.1.2", + "form-data": "^4.0.0", "lodash": "^4.17.21", + "open": "^8.4.0", "simple-json-db": "^2.0.0", "sinon": "^15.0.0", + "tui-image-editor": "^3.15.3", "uuid": "3.3.3", "v-mask": "^2.3.0", "vue": "^2.6.14", diff --git a/public/server/Server.js b/public/server/Server.js new file mode 100644 index 00000000..30689d13 --- /dev/null +++ b/public/server/Server.js @@ -0,0 +1,36 @@ +const express = require("express"); +const bodyParser = require("body-parser"); +const cors = require("cors"); +const path = require("path"); + +const app = express(); +const port = process.env.VUE_APP_SERVER_PORT || 64064; + +const corsOptions = { + origin: `http://localhost:${port}`, +}; + +app.use(cors()); +app.use(cors(corsOptions)); + +// parse requests of content-type - application/json +app.use(bodyParser.json()); + +// parse requests of content-type - application/x-www-form-urlencoded +app.use(bodyParser.urlencoded({ extended: true })); + +// path +app.use(express.static(path.join(__dirname, "images"))); + +app.disable("x-powered-by"); + +// modules +require("./modules/JiraUtility")(app); + +try { + app.listen(port, () => { + console.log(`OAuth redirect server running at http://localhost:${port}`); + }); +} catch (err) { + console.log(err); +} diff --git a/public/server/images/favicon.ico b/public/server/images/favicon.ico new file mode 100644 index 00000000..a914da5e Binary files /dev/null and b/public/server/images/favicon.ico differ diff --git a/public/server/images/logo.png b/public/server/images/logo.png new file mode 100644 index 00000000..bc26babd Binary files /dev/null and b/public/server/images/logo.png differ diff --git a/public/server/jira.html b/public/server/jira.html new file mode 100644 index 00000000..656c7918 --- /dev/null +++ b/public/server/jira.html @@ -0,0 +1,76 @@ + + + + + + + + YATTIE + + + + + + + +
+
+ +
+ You are now connected to JIRA! You can close this window and go back to the YATTIE app to get started + testing. +
+
+ +
+ + + \ No newline at end of file diff --git a/public/server/modules/JiraUtility.js b/public/server/modules/JiraUtility.js new file mode 100644 index 00000000..f0176fe1 --- /dev/null +++ b/public/server/modules/JiraUtility.js @@ -0,0 +1,41 @@ +const open = require("open"); +const path = require("path"); +const ClientOAuth2 = require("client-oauth2"); +const port = process.env.VUE_APP_SERVER_PORT; +const auth = new ClientOAuth2({ + clientId: process.env.VUE_APP_JIRA_CLIENT_ID, + clientSecret: process.env.VUE_APP_JIRA_CLIENT_SECRET, + accessTokenUri: "https://auth.atlassian.com/oauth/token", + authorizationUri: + "https://auth.atlassian.com/authorize?audience=api.atlassian.com&prompt=consent", + redirectUri: `http://localhost:${port}/oauth2/atlassian/callback`, + scopes: ["read:jira-work", "write:jira-work", "read:me", "offline_access"], +}); +module.exports = (app) => { + app.use((req, res, next) => { + res.header( + "Access-Control-Allow-Headers", + "x-access-token, Origin, Content-Type, Accept" + ); + next(); + }); + + app.get("/oauth2/atlassian", (req, res) => { + var uri = auth.code.getUri(); + open(uri, (err) => { + console.log(err); + }); + return res.send(uri); + }); + app.get("/oauth2/atlassian/callback", (req, res) => { + auth.code.getToken(req.originalUrl).then((user) => { + const data = { + type: "jira", + accessToken: user.data, + }; + process.send(data); + + return res.sendFile(path.join(__dirname, "../jira.html")); + }); + }); +}; diff --git a/src/assets/icon/bug.svg b/src/assets/icon/bug.svg new file mode 100644 index 00000000..b937a8b2 --- /dev/null +++ b/src/assets/icon/bug.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icon/list.svg b/src/assets/icon/list.svg new file mode 100644 index 00000000..361c224f --- /dev/null +++ b/src/assets/icon/list.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/background.js b/src/background.js index 4c6ae817..32ef2a37 100644 --- a/src/background.js +++ b/src/background.js @@ -32,8 +32,8 @@ async function createWindow() { if (process.env.WEBPACK_DEV_SERVER_URL) { // Load the url of the dev server if in development mode await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL); - if (isDevelopment){ - win.webContents.openDevTools(); + if (isDevelopment) { + win.webContents.openDevTools(); } } else { createProtocol("app"); diff --git a/src/components/ControlPanel.vue b/src/components/ControlPanel.vue index 3f6b4c0d..840e305b 100644 --- a/src/components/ControlPanel.vue +++ b/src/components/ControlPanel.vue @@ -58,7 +58,7 @@ color="primary" @click="deleteConfirmDialog = true" > - mdi-delete Delete + mdi-delete {{ $tc("caption.delete", 1) }} @@ -70,9 +70,17 @@ color="white" @click="exportItems" > - mdi-download Export + mdi-download {{ $tc("caption.export", 1) }} + + + @@ -482,12 +490,16 @@ import DurationConfirmDialog from "./dialogs/DurationConfirmDialog.vue"; import AudioErrorDialog from "./dialogs/AudioErrorDialog.vue"; import EndSessionDialog from "./dialogs/EndSessionDialog.vue"; import MinimizeControlWrapper from "../components/MinimizeControlWrapper.vue"; + +import JiraExportSession from "./jira/JiraExportSession"; + import { IPC_HANDLERS, IPC_FUNCTIONS, IPC_BIND_KEYS, SESSION_STATUSES, VIDEO_RESOLUTION, + STATUSES, } from "../modules/constants"; import { DEFAULT_MAP_NODES, @@ -515,6 +527,7 @@ export default { AudioErrorDialog, EndSessionDialog, MinimizeControlWrapper, + JiraExportSession, }, props: { items: { @@ -529,6 +542,14 @@ export default { type: Object, default: () => {}, }, + credentialItem: { + type: Object, + default: () => {}, + }, + isAuthenticated: { + type: Boolean, + default: () => false, + }, checkedStatusOfPreSessionTask: { type: Boolean, default: () => false, @@ -560,6 +581,12 @@ export default { configItem: function (newValue) { this.config = newValue; }, + credentialItem: function (newValue) { + this.credential = newValue; + }, + isAuthenticated: function (newValue) { + this.checkAuth = newValue; + }, "$store.state.status": { deep: true, handler(newValue) { @@ -626,6 +653,8 @@ export default { sourceId: this.srcId, itemLists: this.items, config: this.configItem, + credential: this.credentialItem, + checkAuth: this.isAuthenticated, audioDevices: [], loaded: false, status: this.$store.state.status, @@ -997,7 +1026,6 @@ export default { this.durationConfirmDialog = false; this.status = SESSION_STATUSES.PROCEED; this.changeSessionStatus(SESSION_STATUSES.PROCEED); - console.log("start interval-1"); this.startInterval(); }, updateStatus(value) { @@ -1384,7 +1412,6 @@ export default { duration: this.duration, sourceId: this.sourceId, }; - // console.log(data); localStorage.setItem("state-data", JSON.stringify(data)); if (!window.ipc) return; await window.ipc.invoke(IPC_HANDLERS.WINDOW, { @@ -1431,16 +1458,13 @@ export default { path: this.$route.path, }; if (!window.ipc) return; - await window.ipc - .invoke(IPC_HANDLERS.FILE_SYSTEM, { - func: IPC_FUNCTIONS.SAVE_SESSION, - data: data, - }) - .then(() => { - if (callback) { - callback(); - } - }); + const { status } = await window.ipc.invoke(IPC_HANDLERS.FILE_SYSTEM, { + func: IPC_FUNCTIONS.SAVE_SESSION, + data: data, + }); + if (status === STATUSES.SUCCESS && callback) { + callback(); + } }, discardSession(callback = null) { this.newSessionDialog = false; @@ -1449,7 +1473,6 @@ export default { } }, async clearSession() { - console.log("clear session"); this.$root.$emit("new-session"); this.status = SESSION_STATUSES.PENDING; @@ -1475,10 +1498,10 @@ export default { }, }); this.stopInterval(); - // const currentPath = this.$router.history.current.path; - // if (currentPath !== "/main") { - // this.$router.push({ path: "/main" }); - // } + const currentPath = this.$router.history.current.path; + if (currentPath !== "/main") { + this.$router.push({ path: "/main" }); + } }); }, async resetSession() { diff --git a/src/components/ExportPanel.vue b/src/components/ExportPanel.vue index 7dfd92b2..4b3245c5 100644 --- a/src/components/ExportPanel.vue +++ b/src/components/ExportPanel.vue @@ -2,30 +2,84 @@ - + {{ $tc("caption.export_session_report", 1) }} + + + diff --git a/src/components/MinimizeControlWrapper.vue b/src/components/MinimizeControlWrapper.vue index e9e22a36..a41d31fc 100644 --- a/src/components/MinimizeControlWrapper.vue +++ b/src/components/MinimizeControlWrapper.vue @@ -251,7 +251,6 @@ export default { y: event.screenY, }; - console.log(deltaPos); if (!window.ipc) return; window.ipc.invoke(IPC_HANDLERS.WINDOW, { diff --git a/src/components/__tests__/NotesWrapper.spec.js b/src/components/__tests__/NotesWrapper.spec.js index 6dd44244..cb6c4ba8 100644 --- a/src/components/__tests__/NotesWrapper.spec.js +++ b/src/components/__tests__/NotesWrapper.spec.js @@ -19,6 +19,6 @@ describe("NotesWrapper.vue", () => { }, vuetify, }); - + expect(wrapper.find(".content").exists()).toBe(true); }); }); diff --git a/src/components/__tests__/TestWrapper.spec.js b/src/components/__tests__/TestWrapper.spec.js index d9e35828..b217fb52 100644 --- a/src/components/__tests__/TestWrapper.spec.js +++ b/src/components/__tests__/TestWrapper.spec.js @@ -55,8 +55,7 @@ describe("TestWrapper.vue", () => { const charterTabWrapper = wrapper.find(".charter-tab"); expect(charterTabWrapper.findComponent(MindmapEditor).exists()).toBe(false); - - const precondWrapper = wrapper.find(".pre-cond"); + expect(wrapper.find(".pre-cond").exists()).toBe(true); }); test('change the value of "Time limit" input box', async () => { diff --git a/src/components/authentication/SigninWrapper.vue b/src/components/authentication/SigninWrapper.vue index bf3675a8..48eaf10b 100644 --- a/src/components/authentication/SigninWrapper.vue +++ b/src/components/authentication/SigninWrapper.vue @@ -10,13 +10,27 @@
+
+ +
- + +
{{ $tc("caption.signin_jira", 1) }}
@@ -50,29 +64,181 @@ class="text-capitalize pa-0 signup-btn" color="primary" plain - to="/authentication/signup2" + to="/authentication/signupMain" > {{ $tc("caption.sign_up", 1) }}
-->
+ + {{ snackBar.message }} + + @@ -112,6 +278,7 @@ export default { margin-left: -50px; } .content { + position: relative; background-color: #fff; border-radius: 8px; padding: 32px 40px; @@ -168,4 +335,13 @@ export default { font-weight: 500; color: #6d28d9; } + +.loading-wrapper { + position: absolute; + overflow: hidden; + z-index: 9999999; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} diff --git a/src/components/authentication/SignupHomeWrapper.vue b/src/components/authentication/SignupHomeWrapper.vue index 0ec47daf..920bf7e5 100644 --- a/src/components/authentication/SignupHomeWrapper.vue +++ b/src/components/authentication/SignupHomeWrapper.vue @@ -5,7 +5,7 @@
-
+
+ +
{{ $tc("caption.signup_yattie", 1) }}
- +
{{ $tc("caption.signup_jira", 1) }}
@@ -26,12 +40,12 @@
-
{{ $tc("caption.singup_qtest", 1) }}
+
{{ $tc("caption.signup_qtest", 1) }}
- {{ $tc("caption.signup_pratictest", 1) }} + {{ $tc("caption.signup_practitest", 1) }}
@@ -49,7 +63,7 @@ fill small block - to="/authentication/signup3" + to="/authentication/signupYattie" > {{ $tc("caption.sign_up", 1) }} @@ -80,29 +94,165 @@ {{ $t("message.signup_policy") }} - {{ $tc("caption.term_data_policy", 1) }} + {{ $tc("caption.signup_term_data_policy", 1) }} {{ $tc("caption.and", 1) }}   - {{ $tc("caption.cookie_policy", 1) }} + {{ $tc("caption.signup_cookie_policy", 1) }} .
+ + {{ snackBar.message }} + + diff --git a/src/components/authentication/SignupYattieWrapper.vue b/src/components/authentication/SignupYattieWrapper.vue index 32acdc58..d632a18f 100644 --- a/src/components/authentication/SignupYattieWrapper.vue +++ b/src/components/authentication/SignupYattieWrapper.vue @@ -4,7 +4,7 @@ mdi-chevron-left {{ $tc("caption.back", 1) }} @@ -79,12 +79,12 @@ {{ $t("message.signup_policy") }} - {{ $tc("caption.term_data_policy", 1) }} + {{ $tc("caption.signup_term_data_policy", 1) }} {{ $tc("caption.and", 1) }}   - {{ $tc("caption.cookie_policy", 1) }} + {{ $tc("caption.signup_cookie_policy", 1) }} . diff --git a/src/components/dialogs/NoteDialog.vue b/src/components/dialogs/NoteDialog.vue index 04857f8f..aad1e83f 100644 --- a/src/components/dialogs/NoteDialog.vue +++ b/src/components/dialogs/NoteDialog.vue @@ -1,5 +1,12 @@