n.data.id)
- .filter((n) => n.data.id === d.data.id)
- .select('.node-loader')
- .remove();
- this.blurHighlight();
- return;
- }
+ const result = await axiosClient.get(domain);
+ let body = result.data;
- if (body.nodes.length === 1) {
+ if (
+ !body ||
+ Object.keys(body).length === 0 ||
+ body.nodes.length === 0 ||
+ body.nodes.length === 1
+ ) {
this.pushAlert('noChildren', d.data.nodeLabel);
this.isShifting = null;
this.svg
diff --git a/general/nuxt.config.ts b/general/nuxt.config.ts
index c324955c..c99b4527 100644
--- a/general/nuxt.config.ts
+++ b/general/nuxt.config.ts
@@ -150,7 +150,12 @@ export default defineNuxtConfig({
'@/assets/scss/Ontology.scss',
'vue-multiselect/dist/vue-multiselect.css'
],
- modules: ['@nuxtjs/google-fonts', '@pinia/nuxt', '@zadigetvoltaire/nuxt-gtm'],
+ modules: [
+ '@nuxtjs/google-fonts',
+ '@pinia/nuxt',
+ '@pinia-plugin-persistedstate/nuxt',
+ '@zadigetvoltaire/nuxt-gtm'
+ ],
googleFonts: {
families: {
Inter: [400, 600, 700, 800]
diff --git a/general/package-lock.json b/general/package-lock.json
index ee67bd46..100243c6 100644
--- a/general/package-lock.json
+++ b/general/package-lock.json
@@ -10,7 +10,7 @@
"hasInstallScript": true,
"dependencies": {
"@ewoudenberg/difflib": "^0.1.0",
- "@pinia/nuxt": "^0.4.11",
+ "@pinia/nuxt": "^0.5.1",
"@popperjs/core": "^2.11.8",
"@zadigetvoltaire/nuxt-gtm": "^0.0.13",
"axios": "^1.6.0",
@@ -22,7 +22,7 @@
"highlight.js": "^11.8.0",
"linkify-html": "^4.1.1",
"linkifyjs": "^4.1.1",
- "pinia": "^2.1.6",
+ "pinia": "^2.1.7",
"qs": "^6.11.2",
"string-comparison": "^1.2.0",
"vue-multiselect": "^3.0.0-beta.2"
@@ -31,6 +31,7 @@
"@nuxt/devtools": "^1.0.0",
"@nuxt/eslint-config": "^0.2.0",
"@nuxtjs/google-fonts": "^3.0.2",
+ "@pinia-plugin-persistedstate/nuxt": "^1.2.0",
"@types/bootstrap": "^5.2.6",
"@types/markdown-it": "^13.0.2",
"@types/node": "^18.17.3",
@@ -2262,13 +2263,27 @@
"node": ">=0.10"
}
},
+ "node_modules/@pinia-plugin-persistedstate/nuxt": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@pinia-plugin-persistedstate/nuxt/-/nuxt-1.2.0.tgz",
+ "integrity": "sha512-2rtgx5viGSMQMCoFYZMHguA2FhFKCUvw0PwETfqQegsWeBHlqk1/D0G/9xqep8Hq+c1BuFx+jNLJzoLXtYfivg==",
+ "dev": true,
+ "dependencies": {
+ "@nuxt/kit": "^3.8.0",
+ "defu": "^6.1.2",
+ "pinia-plugin-persistedstate": ">=3.2.0"
+ },
+ "peerDependencies": {
+ "@pinia/nuxt": "^0.5.0"
+ }
+ },
"node_modules/@pinia/nuxt": {
- "version": "0.4.11",
- "resolved": "https://registry.npmjs.org/@pinia/nuxt/-/nuxt-0.4.11.tgz",
- "integrity": "sha512-bhuNFngJpmBCdAqWguezNJ/oJFR7wvKieqiZrmmdmPR07XjsidAw8RLXHMZE9kUm32M9E6T057OBbG/22jERTg==",
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/@pinia/nuxt/-/nuxt-0.5.1.tgz",
+ "integrity": "sha512-6wT6TqY81n+7/x3Yhf0yfaJVKkZU42AGqOR0T3+UvChcaOJhSma7OWPN64v+ptYlznat+fS1VTwNAcbi2lzHnw==",
"dependencies": {
"@nuxt/kit": "^3.5.0",
- "pinia": ">=2.1.0"
+ "pinia": ">=2.1.7"
},
"funding": {
"url": "https://github.com/sponsors/posva"
@@ -8735,6 +8750,15 @@
}
}
},
+ "node_modules/pinia-plugin-persistedstate": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-3.2.1.tgz",
+ "integrity": "sha512-MK++8LRUsGF7r45PjBFES82ISnPzyO6IZx3CH5vyPseFLZCk1g2kgx6l/nW8pEBKxxd4do0P6bJw+mUSZIEZUQ==",
+ "dev": true,
+ "peerDependencies": {
+ "pinia": "^2.0.0"
+ }
+ },
"node_modules/pkg-types": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz",
diff --git a/general/package.json b/general/package.json
index 451b0c5e..b9d9157c 100644
--- a/general/package.json
+++ b/general/package.json
@@ -13,7 +13,7 @@
},
"dependencies": {
"@ewoudenberg/difflib": "^0.1.0",
- "@pinia/nuxt": "^0.4.11",
+ "@pinia/nuxt": "^0.5.1",
"@popperjs/core": "^2.11.8",
"@zadigetvoltaire/nuxt-gtm": "^0.0.13",
"axios": "^1.6.0",
@@ -25,7 +25,7 @@
"highlight.js": "^11.8.0",
"linkify-html": "^4.1.1",
"linkifyjs": "^4.1.1",
- "pinia": "^2.1.6",
+ "pinia": "^2.1.7",
"qs": "^6.11.2",
"string-comparison": "^1.2.0",
"vue-multiselect": "^3.0.0-beta.2"
@@ -34,6 +34,7 @@
"@nuxt/devtools": "^1.0.0",
"@nuxt/eslint-config": "^0.2.0",
"@nuxtjs/google-fonts": "^3.0.2",
+ "@pinia-plugin-persistedstate/nuxt": "^1.2.0",
"@types/bootstrap": "^5.2.6",
"@types/markdown-it": "^13.0.2",
"@types/node": "^18.17.3",
diff --git a/general/pages/auth/login.vue b/general/pages/auth/login.vue
new file mode 100644
index 00000000..4d6448c4
--- /dev/null
+++ b/general/pages/auth/login.vue
@@ -0,0 +1,183 @@
+
+
+
+
+
+
Login
+
+ {{ error }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/general/pages/auth/recover-password.vue b/general/pages/auth/recover-password.vue
new file mode 100644
index 00000000..8cf1986f
--- /dev/null
+++ b/general/pages/auth/recover-password.vue
@@ -0,0 +1,168 @@
+
+
+
+
+
+
Recover password
+
+
+ {{ error }}
+
+
+
+
+
+
+
+
+
+
diff --git a/general/pages/ontology/[...resource].vue b/general/pages/ontology/[...resource].vue
index fb44e9ae..f186e843 100644
--- a/general/pages/ontology/[...resource].vue
+++ b/general/pages/ontology/[...resource].vue
@@ -767,6 +767,10 @@
:ontology-name-uppercase="ontologyNameUppercase"
/>
+
+
@@ -830,7 +834,7 @@ export default {
if (this.isComparing) {
this.fetchCompareDataAndMerge(this.query);
this.scrollToOntologyViewerTopOfContainer();
- } else this.fetchData(this.query);
+ } else this.fetchEntity(this.query);
});
}
if (!to.query.search) {
@@ -957,6 +961,12 @@ export default {
missingImportsServer: (store) => store.missingImportsServer,
ontologyServerCompare: (store) => store.ontologyServerCompare
}),
+ ...mapState(useOntologyStore, {
+ unauthorizedError: (store) => store.unauthorizedError
+ }),
+ ...mapState(useAuthStore, {
+ jwt: (store) => store.jwt
+ }),
isError() {
return (
this.error.versions ||
@@ -964,7 +974,8 @@ export default {
this.error.properties ||
this.error.search ||
this.error.entityData ||
- this.error.entityNotFound
+ this.error.entityNotFound ||
+ this.unauthorizedError
);
},
isLoader() {
@@ -987,6 +998,11 @@ export default {
);
}
},
+ watch: {
+ jwt() {
+ this.fetchData();
+ }
+ },
async mounted() {
let queryParam = '';
@@ -1014,12 +1030,7 @@ export default {
this.scrollToOntologyViewerTopOfContainer();
}
- this.updateServers(this.$route);
- this.updateCompareServers(null);
- this.fetchModules();
- this.fetchSearchProperties();
- await this.fetchVersions();
- this.fetchData(this.query, { noScroll: true });
+ await this.fetchData();
// disable input autocomplete in multiselect
this.$refs.searchBoxInputMobile.$refs.search.setAttribute(
@@ -1047,9 +1058,19 @@ export default {
'getEntityData',
'initialEntityLoad',
'setReleases',
- 'getErrorFlags'
+ 'getErrorFlags',
+ 'clearUnauthorizedError'
]),
- async fetchData(iri, options) {
+ async fetchData() {
+ this.updateServers(this.$route);
+ this.updateCompareServers(null);
+ this.fetchModules();
+ this.fetchSearchProperties();
+ await this.fetchVersions();
+ this.fetchEntity(this.query, { noScroll: true });
+ },
+ async fetchEntity(iri, options) {
+ this.clearUnauthorizedError();
const noScroll = options?.noScroll;
if (iri) {
if (!noScroll) this.scrollToOntologyViewerTopOfContainer();
@@ -1091,10 +1112,9 @@ export default {
},
async fetchVersions() {
try {
- const result = await getOntologyVersions(
+ const ontologyVersions = await getOntologyVersions(
`/${this.ontologyName}/ontology/api/`
);
- const ontologyVersions = await result.json();
const first = 'master/latest';
ontologyVersions.sort((x, y) =>
@@ -1152,24 +1172,21 @@ export default {
const tagName = runtimeConfig.public.tagName;
// group versions by tags, pull requests and releases
- const tagsResult = await getJenkinsJobs(
+ const tagsJson = await getJenkinsJobs(
`${jenkinsJobUrl}/view/tags/api/json`
);
- const tagsJson = await tagsResult.json();
const tags = tagsJson.jobs.map((item) => item.name.toLowerCase());
- const pullRequestsResult = await getJenkinsJobs(
+ const pullRequestsJson = await getJenkinsJobs(
`${jenkinsJobUrl}/view/change-requests/api/json`
);
- const pullRequestsJson = await pullRequestsResult.json();
const pullRequests = pullRequestsJson.jobs.map((item) =>
item.name.toLowerCase()
);
- const defaultViewResult = await getJenkinsJobs(
+ const defaultViewJson = await getJenkinsJobs(
`${jenkinsJobUrl}/view/default/api/json`
);
- const defaultViewJson = await defaultViewResult.json();
const defaultView = defaultViewJson.jobs.map((item) =>
item.name.toLowerCase()
);
@@ -1231,8 +1248,7 @@ export default {
},
async fetchModules() {
try {
- const result = await getModules(this.modulesServer);
- this.modulesList = await result.json();
+ this.modulesList = await getModules(this.modulesServer);
this.error.modules = false;
} catch (err) {
console.error(err);
@@ -1241,10 +1257,9 @@ export default {
},
async fetchSearchProperties() {
try {
- const result = await getFindProperties(
+ this.searchBox.findPropertiesAll = await getFindProperties(
`${this.searchServer}/properties`
);
- this.searchBox.findPropertiesAll = await result.json();
if (this.searchBox.findPropertiesAll.length > 0) {
this.searchBox.findProperties.push(
@@ -1414,7 +1429,7 @@ export default {
this.fetchCompareDataAndMerge(this.query);
} else {
this.updateCompareServers(version['@id']);
- this.fetchData(this.query, { noScroll: true });
+ this.fetchEntity(this.query, { noScroll: true });
}
},
swapSelectedVersions() {
@@ -1447,7 +1462,7 @@ export default {
) {
this.fetchCompareDataAndMerge(this.query);
} else if (!isCompareExpanded && this.data == null)
- this.fetchData(this.query, { noScroll: true });
+ this.fetchEntity(this.query, { noScroll: true });
},
searchBox_limitText(count) {
return `and ${count} other results`;
@@ -1520,8 +1535,7 @@ export default {
`${this.searchServer}?term=${searchBQuery}&mode=advance&useHighlighting=${isHighlighting}&findProperties=${this.searchBox.encodedProperties}&page=${page}`
);
- const result = await getFindSearch(domain);
- const body = await result.json();
+ const body = await getFindSearch(domain);
this.searchBox.pageResults = body.results;
@@ -1581,8 +1595,7 @@ export default {
`${this.searchServer}?term=${query}&mode=advance&useHighlighting=false&findProperties=${this.searchBox.encodedProperties}`
);
const result = await getFindSearch(domain);
- const json = await result.json();
- const hints = json.results;
+ const hints = result.results;
hints.forEach((el) => {
// eslint-disable-next-line no-param-reassign
diff --git a/general/stores/auth.ts b/general/stores/auth.ts
new file mode 100644
index 00000000..e8468fdb
--- /dev/null
+++ b/general/stores/auth.ts
@@ -0,0 +1,48 @@
+import { defineStore } from 'pinia';
+
+export interface UserData {
+ id: number;
+ username: string;
+ email: string;
+ provider: string;
+ confirmed: boolean;
+ blocked: boolean;
+ createdAt: string;
+ updatedAt: string;
+ role: {
+ id: number;
+ name: string;
+ description: string;
+ type: string;
+ createdAt: string;
+ updatedAt: string;
+ };
+}
+
+interface AuthState {
+ jwt: string | null;
+ user: UserData | null;
+}
+
+export const useAuthStore = defineStore({
+ id: 'auth-store',
+ state: (): AuthState => {
+ return {
+ jwt: null,
+ user: null
+ };
+ },
+ actions: {
+ setJwt(token: string) {
+ this.jwt = token;
+ },
+ setUserData(user: UserData) {
+ this.user = user;
+ },
+ clear() {
+ this.jwt = null;
+ this.user = null;
+ }
+ },
+ persist: true
+});
diff --git a/general/stores/authModal.ts b/general/stores/authModal.ts
new file mode 100644
index 00000000..0588fcfe
--- /dev/null
+++ b/general/stores/authModal.ts
@@ -0,0 +1,24 @@
+import { defineStore } from 'pinia';
+
+type ModalKey = 'login' | 'register' | 'recover';
+
+interface AuthModalState {
+ authModal: ModalKey | null;
+}
+
+export const useAuthModalStore = defineStore({
+ id: 'auth-modal-store',
+ state: (): AuthModalState => {
+ return {
+ authModal: null
+ };
+ },
+ actions: {
+ openModal(modal: ModalKey) {
+ this.authModal = modal;
+ },
+ closeModal() {
+ this.authModal = null;
+ }
+ }
+});
diff --git a/general/stores/configuration.ts b/general/stores/configuration.ts
index ae6df310..88f92832 100644
--- a/general/stores/configuration.ts
+++ b/general/stores/configuration.ts
@@ -12,7 +12,8 @@ export const useConfigurationStore = defineStore({
ontoviewerServerUrl: null as any,
ontologyRepositoryUrl: null as any,
defaultBranchName: null as any,
- jenkinsJobUrl: null as any
+ jenkinsJobUrl: null as any,
+ authEnabled: null as any
}
};
},
@@ -32,6 +33,7 @@ export const useConfigurationStore = defineStore({
this.config.ontologyRepositoryUrl = `https://github.com/edmcouncil/${this.config.ontpubFamily}`;
this.config.defaultBranchName = 'current';
this.config.jenkinsJobUrl = null;
+ this.config.authEnabled = null;
const configData = await getAppConfigurationData(runtimeConfig);
this.setConfigurationData(configData);
diff --git a/general/stores/ontology.ts b/general/stores/ontology.ts
index 36bfd2b9..fb68a5ca 100644
--- a/general/stores/ontology.ts
+++ b/general/stores/ontology.ts
@@ -10,7 +10,8 @@ export const useOntologyStore = defineStore({
iri: '' as string,
entityData: {} as Record
,
releases: [] as Array,
- errorFlags: {} as Record
+ errorFlags: {} as Record,
+ unauthorizedError: false
};
},
actions: {
@@ -49,22 +50,20 @@ export const useOntologyStore = defineStore({
const domain = `${servers.getVersionedOntologyServer(version)}?iri=${iri}`;
const response = await getEntity(domain);
- if (response.ok) {
- this.errorFlags[versionIdentifier] = false;
- return await response.json();
- } else {
- this.errorFlags[versionIdentifier] = true;
- return null;
- }
+ this.errorFlags[versionIdentifier] = false;
+ return response;
} catch (error: any) {
- if (error.status == 404) {
+ if (error.response && error.response.status === 404) {
// Resource doesn't exist in this version
this.errorFlags[versionIdentifier] = false;
return null;
- } else if (error.status == 503) {
+ } else if (error.response && error.response.status === 503) {
// Server error
this.errorFlags[versionIdentifier] = true;
return null;
+ } else {
+ this.errorFlags[versionIdentifier] = true;
+ return null;
}
}
},
@@ -82,6 +81,9 @@ export const useOntologyStore = defineStore({
clearData(): void {
this.entityData = {};
},
+ clearUnauthorizedError() {
+ this.unauthorizedError = false;
+ },
setReleases(releases: Array) {
this.releases = releases;
},
From 333d1b1da1c4b19c4cd65f35db0569637c68bb28 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adam=20Roso=C5=82owski?=
<87621210+rr-adam@users.noreply.github.com>
Date: Thu, 20 Jun 2024 11:49:33 +0200
Subject: [PATCH 2/9] Update password recovery process
---
general/assets/scss/global.scss | 1 +
general/components/Header/AuthComponent.vue | 2 +-
.../components/Header/AuthRecoverModal.vue | 112 ++------------
general/components/Header/AuthResetModal.vue | 139 ++++++++++++++++++
general/pages/ontology/[...resource].vue | 6 +-
general/stores/authModal.ts | 2 +-
6 files changed, 157 insertions(+), 105 deletions(-)
create mode 100644 general/components/Header/AuthResetModal.vue
diff --git a/general/assets/scss/global.scss b/general/assets/scss/global.scss
index f4591412..97cef6f7 100644
--- a/general/assets/scss/global.scss
+++ b/general/assets/scss/global.scss
@@ -699,6 +699,7 @@ a.deprecated:hover {
.modal.login-modal,
.modal.recover-modal,
+.modal.reset-modal,
.modal.register-modal {
.modal-header {
position: relative;
diff --git a/general/components/Header/AuthComponent.vue b/general/components/Header/AuthComponent.vue
index 64e627cc..782009bf 100644
--- a/general/components/Header/AuthComponent.vue
+++ b/general/components/Header/AuthComponent.vue
@@ -3,6 +3,7 @@
+
diff --git a/general/pages/ontology/[...resource].vue b/general/pages/ontology/[...resource].vue
index f186e843..a6966437 100644
--- a/general/pages/ontology/[...resource].vue
+++ b/general/pages/ontology/[...resource].vue
@@ -1020,9 +1020,9 @@ export default {
queryParam = this.$route.query.query + this.$route.hash || '';
}
this.query = queryParam;
-
+ console.log(this.$route.query.recoveryCode);
const scrollTopElement = this.$refs['article-top-element'];
- if (!this.query) {
+ if (!this.query && !this.$route.query.recoveryCode) {
scrollTopElement.scrollIntoView({
behavior: 'smooth'
});
@@ -1676,6 +1676,8 @@ export default {
});
},
scrollToOntologyViewerTopOfContainer(behavior) {
+ if (this.$route.query.recoveryCode) return;
+
const element = this.$refs.ontologyViewerTopOfContainer;
const rect = element.getBoundingClientRect();
diff --git a/general/stores/authModal.ts b/general/stores/authModal.ts
index 0588fcfe..09a2201a 100644
--- a/general/stores/authModal.ts
+++ b/general/stores/authModal.ts
@@ -1,6 +1,6 @@
import { defineStore } from 'pinia';
-type ModalKey = 'login' | 'register' | 'recover';
+type ModalKey = 'login' | 'register' | 'reset' | 'recover';
interface AuthModalState {
authModal: ModalKey | null;
From 0d6e8750e5e82ee8c34a1aaebe5207326701e661 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adam=20Roso=C5=82owski?=
<87621210+rr-adam@users.noreply.github.com>
Date: Thu, 20 Jun 2024 14:00:17 +0200
Subject: [PATCH 3/9] Notifications and email validation development
---
general/api/ontology.js | 5 +-
general/assets/scss/global.scss | 1 +
general/components/Header/AuthComponent.vue | 1 +
.../Header/AuthConfirmEmailModal.vue | 63 ++++++
general/components/Header/AuthLoginModal.vue | 4 +
.../components/Header/AuthRegisterModal.vue | 171 ++++++++--------
general/components/Header/AuthResetModal.vue | 1 +
.../Ontology/GraphVisualization.vue | 2 +-
general/components/Ontology/Toast.vue | 56 ++++++
.../components/Ontology/ToastContainer.vue | 32 +++
general/layouts/default.vue | 1 +
general/layouts/minimal.vue | 1 +
general/pages/auth/login.vue | 183 ------------------
general/pages/auth/recover-password.vue | 168 ----------------
general/pages/ontology/[...resource].vue | 11 +-
general/stores/authModal.ts | 2 +-
general/stores/toast.ts | 34 ++++
17 files changed, 295 insertions(+), 441 deletions(-)
create mode 100644 general/components/Header/AuthConfirmEmailModal.vue
create mode 100644 general/components/Ontology/Toast.vue
create mode 100644 general/components/Ontology/ToastContainer.vue
delete mode 100644 general/pages/auth/login.vue
delete mode 100644 general/pages/auth/recover-password.vue
create mode 100644 general/stores/toast.ts
diff --git a/general/api/ontology.js b/general/api/ontology.js
index 235c9348..f8c5839b 100644
--- a/general/api/ontology.js
+++ b/general/api/ontology.js
@@ -2,7 +2,8 @@ import axios from 'axios';
import {
useAuthStore,
useOntologyStore,
- useConfigurationStore
+ useConfigurationStore,
+ useToastStore
} from '#imports';
export const axiosClient = axios.create();
@@ -28,10 +29,12 @@ axiosClient.interceptors.request.use((config) => {
axiosClient.interceptors.response.use(
(response) => response,
(error) => {
+ const toastStore = useToastStore();
const authStore = useAuthStore();
const ontologyStore = useOntologyStore();
if (error.response && error.response.status === 401) {
+ toastStore.addToast('Session expired. Please log in again.');
authStore.clear();
}
if (error.response && error.response.status === 403) {
diff --git a/general/assets/scss/global.scss b/general/assets/scss/global.scss
index 97cef6f7..a73f22d0 100644
--- a/general/assets/scss/global.scss
+++ b/general/assets/scss/global.scss
@@ -700,6 +700,7 @@ a.deprecated:hover {
.modal.login-modal,
.modal.recover-modal,
.modal.reset-modal,
+.modal.confirmEmail-modal,
.modal.register-modal {
.modal-header {
position: relative;
diff --git a/general/components/Header/AuthComponent.vue b/general/components/Header/AuthComponent.vue
index 782009bf..d288ac7e 100644
--- a/general/components/Header/AuthComponent.vue
+++ b/general/components/Header/AuthComponent.vue
@@ -4,6 +4,7 @@
+
-
diff --git a/general/layouts/minimal.vue b/general/layouts/minimal.vue
index c911c21e..95b89f0d 100644
--- a/general/layouts/minimal.vue
+++ b/general/layouts/minimal.vue
@@ -4,6 +4,7 @@
+
diff --git a/general/pages/auth/login.vue b/general/pages/auth/login.vue
deleted file mode 100644
index 4d6448c4..00000000
--- a/general/pages/auth/login.vue
+++ /dev/null
@@ -1,183 +0,0 @@
-
-
-
-
-
-
Login
-
- {{ error }}
-
-
-
-
-
-
-
-
-
-
-
diff --git a/general/pages/auth/recover-password.vue b/general/pages/auth/recover-password.vue
deleted file mode 100644
index 8cf1986f..00000000
--- a/general/pages/auth/recover-password.vue
+++ /dev/null
@@ -1,168 +0,0 @@
-
-
-
-
-
-
Recover password
-
-
- {{ error }}
-
-
-
-
-
-
-
-
-
-
diff --git a/general/pages/ontology/[...resource].vue b/general/pages/ontology/[...resource].vue
index a6966437..70ae4076 100644
--- a/general/pages/ontology/[...resource].vue
+++ b/general/pages/ontology/[...resource].vue
@@ -1020,9 +1020,13 @@ export default {
queryParam = this.$route.query.query + this.$route.hash || '';
}
this.query = queryParam;
- console.log(this.$route.query.recoveryCode);
+
const scrollTopElement = this.$refs['article-top-element'];
- if (!this.query && !this.$route.query.recoveryCode) {
+ if (
+ !this.query &&
+ !this.$route.query.recoveryCode &&
+ !this.$route.query.confirmation
+ ) {
scrollTopElement.scrollIntoView({
behavior: 'smooth'
});
@@ -1676,7 +1680,8 @@ export default {
});
},
scrollToOntologyViewerTopOfContainer(behavior) {
- if (this.$route.query.recoveryCode) return;
+ if (this.$route.query.recoveryCode || this.$route.query.confirmation)
+ return;
const element = this.$refs.ontologyViewerTopOfContainer;
diff --git a/general/stores/authModal.ts b/general/stores/authModal.ts
index 09a2201a..2d71e108 100644
--- a/general/stores/authModal.ts
+++ b/general/stores/authModal.ts
@@ -1,6 +1,6 @@
import { defineStore } from 'pinia';
-type ModalKey = 'login' | 'register' | 'reset' | 'recover';
+type ModalKey = 'login' | 'register' | 'reset' | 'recover' | 'confirmEmail';
interface AuthModalState {
authModal: ModalKey | null;
diff --git a/general/stores/toast.ts b/general/stores/toast.ts
new file mode 100644
index 00000000..a46f59cb
--- /dev/null
+++ b/general/stores/toast.ts
@@ -0,0 +1,34 @@
+import { defineStore } from 'pinia';
+
+type ToastType = 'default' | 'success' | 'warning' | 'error';
+
+interface Toast {
+ id: number;
+ message: string;
+ type: ToastType;
+}
+
+interface ToastState {
+ toasts: Toast[];
+ nextId: number;
+}
+
+export const useToastStore = defineStore({
+ id: 'toast',
+ state: (): ToastState => ({
+ toasts: [],
+ nextId: 0
+ }),
+ actions: {
+ addToast(message: string, type: ToastType = 'default') {
+ const id = this.nextId++;
+ this.toasts.push({ id, message, type });
+ setTimeout(() => {
+ this.removeToast(id);
+ }, 5000);
+ },
+ removeToast(id: number) {
+ this.toasts = this.toasts.filter((toast) => toast.id !== id);
+ }
+ }
+});
From 8870fbddbffeca37854548b3331017fd21463606 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adam=20Roso=C5=82owski?=
<87621210+rr-adam@users.noreply.github.com>
Date: Mon, 24 Jun 2024 14:27:18 +0200
Subject: [PATCH 4/9] Add field validation for registration and password
recovery
---
general/components/Header/AuthLoginModal.vue | 13 +-
.../components/Header/AuthRecoverModal.vue | 78 ++++--
.../components/Header/AuthRegisterModal.vue | 257 +++++++++++-------
general/components/Header/AuthResetModal.vue | 134 ++++++---
general/components/UI/CustomInput.vue | 76 +++---
general/composables/useFormValidation.ts | 121 +++++++++
general/helpers/inputValidation.ts | 49 ++++
7 files changed, 524 insertions(+), 204 deletions(-)
create mode 100644 general/composables/useFormValidation.ts
create mode 100644 general/helpers/inputValidation.ts
diff --git a/general/components/Header/AuthLoginModal.vue b/general/components/Header/AuthLoginModal.vue
index 25eb4282..fc179ee3 100644
--- a/general/components/Header/AuthLoginModal.vue
+++ b/general/components/Header/AuthLoginModal.vue
@@ -6,11 +6,6 @@
footer-class="d-none"
:can-escape="true"
@on-modal-hidden="hideModal"
- @hidden="
- () => {
- renderForm = false;
- }
- "
>
Login
@@ -23,7 +18,7 @@
>
-
+
{{ error }}