Merge pull request 'Removed vue-class-component in favour of composition API' (#2) from vue-composition-api into dev

Reviewed-on: #2
This commit is contained in:
Carlos Jimenez Ruiz 2022-03-08 10:37:48 +00:00
commit cea499936f
11 changed files with 126 additions and 208 deletions

15
package-lock.json generated
View File

@ -13,7 +13,6 @@
"core-js": "^3.6.5", "core-js": "^3.6.5",
"quasar": "^2.0.0", "quasar": "^2.0.0",
"vue": "^3.0.0", "vue": "^3.0.0",
"vue-class-component": "^8.0.0-0",
"vue-i18n": "^9.1.0", "vue-i18n": "^9.1.0",
"vue-router": "^4.0.0-0", "vue-router": "^4.0.0-0",
"vuex": "^4.0.0-0" "vuex": "^4.0.0-0"
@ -19418,14 +19417,6 @@
"@vue/shared": "3.2.31" "@vue/shared": "3.2.31"
} }
}, },
"node_modules/vue-class-component": {
"version": "8.0.0-rc.1",
"resolved": "https://registry.npmmirror.com/vue-class-component/-/vue-class-component-8.0.0-rc.1.tgz",
"integrity": "sha512-w1nMzsT/UdbDAXKqhwTmSoyuJzUXKrxLE77PCFVuC6syr8acdFDAq116xgvZh9UCuV0h+rlCtxXolr3Hi3HyPQ==",
"peerDependencies": {
"vue": "^3.0.0"
}
},
"node_modules/vue-cli-plugin-i18n": { "node_modules/vue-cli-plugin-i18n": {
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmmirror.com/vue-cli-plugin-i18n/-/vue-cli-plugin-i18n-2.3.1.tgz", "resolved": "https://registry.npmmirror.com/vue-cli-plugin-i18n/-/vue-cli-plugin-i18n-2.3.1.tgz",
@ -37109,12 +37100,6 @@
"@vue/shared": "3.2.31" "@vue/shared": "3.2.31"
} }
}, },
"vue-class-component": {
"version": "8.0.0-rc.1",
"resolved": "https://registry.npmmirror.com/vue-class-component/-/vue-class-component-8.0.0-rc.1.tgz",
"integrity": "sha512-w1nMzsT/UdbDAXKqhwTmSoyuJzUXKrxLE77PCFVuC6syr8acdFDAq116xgvZh9UCuV0h+rlCtxXolr3Hi3HyPQ==",
"requires": {}
},
"vue-cli-plugin-i18n": { "vue-cli-plugin-i18n": {
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmmirror.com/vue-cli-plugin-i18n/-/vue-cli-plugin-i18n-2.3.1.tgz", "resolved": "https://registry.npmmirror.com/vue-cli-plugin-i18n/-/vue-cli-plugin-i18n-2.3.1.tgz",

View File

@ -16,7 +16,6 @@
"core-js": "^3.6.5", "core-js": "^3.6.5",
"quasar": "^2.0.0", "quasar": "^2.0.0",
"vue": "^3.0.0", "vue": "^3.0.0",
"vue-class-component": "^8.0.0-0",
"vue-i18n": "^9.1.0", "vue-i18n": "^9.1.0",
"vue-router": "^4.0.0-0", "vue-router": "^4.0.0-0",
"vuex": "^4.0.0-0" "vuex": "^4.0.0-0"
@ -49,4 +48,4 @@
"vue-cli-plugin-quasar": "~4.0.4", "vue-cli-plugin-quasar": "~4.0.4",
"vue-jest": "^5.0.0-0" "vue-jest": "^5.0.0-0"
} }
} }

View File

@ -2,12 +2,6 @@
<router-view></router-view> <router-view></router-view>
</template> </template>
<script lang="ts">
import { Vue } from 'vue-class-component';
export default class App extends Vue {}
</script>
<style lang="scss"> <style lang="scss">
.body--light { .body--light {
background-color: #ccc; background-color: #ccc;

View File

@ -27,7 +27,7 @@
<q-btn dense flat no-wrap> <q-btn dense flat no-wrap>
<q-avatar size="lg"> <q-avatar size="lg">
<q-img <q-img
:src="`/api/Images/user/160x160/${user.id}/download?access_token=${token}`" :src="`/api/Images/user/160x160/${user.id}/download?access_token=${user.token}`"
spinner-color="white" spinner-color="white"
/> />
</q-avatar> </q-avatar>
@ -40,8 +40,9 @@
</q-header> </q-header>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { Options, Vue } from 'vue-class-component'; import { computed } from 'vue';
import { useStore } from 'vuex';
import UserPanel from '@/components/UserPanel.vue'; import UserPanel from '@/components/UserPanel.vue';
interface UserProfile { interface UserProfile {
@ -51,18 +52,13 @@ interface UserProfile {
token: string; token: string;
} }
@Options({ const store = useStore();
components: { const user = computed((): UserProfile => {
UserPanel, return {
}, id: store.state.user.id,
}) username: store.state.user.username,
export default class Topbar extends Vue { nickname: store.state.user.nickname,
get user(): UserProfile { token: store.getters.token,
return this.$store.state.user; };
} });
get token(): string {
return this.$store.getters.token;
}
}
</script> </script>

View File

@ -2,16 +2,16 @@
<q-menu> <q-menu>
<div class="row no-wrap q-pa-md"> <div class="row no-wrap q-pa-md">
<div class="column"> <div class="column">
<div class="text-h6 q-mb-md">{{ $t('components.userPanel.settings') }}</div> <div class="text-h6 q-mb-md">{{ t('components.userPanel.settings') }}</div>
<q-toggle <q-toggle
:label="$t(`globals.lang['${language}']`)" :label="t(`globals.lang['${locale}']`)"
icon="public" icon="public"
color="orange" color="orange"
false-value="es" false-value="es"
true-value="en" true-value="en"
v-model="language" v-model="locale"
/> />
<q-toggle v-model="mode" checked-icon="dark_mode" color="orange" unchecked-icon="light_mode" /> <q-toggle v-model="darkMode" checked-icon="dark_mode" color="orange" unchecked-icon="light_mode" />
<q-btn color="orange" outline size="sm" label="Settings" icon="settings" /> <q-btn color="orange" outline size="sm" label="Settings" icon="settings" />
</div> </div>
@ -21,7 +21,7 @@
<div class="column items-center" style="min-width: 150px"> <div class="column items-center" style="min-width: 150px">
<q-avatar size="80px"> <q-avatar size="80px">
<q-img <q-img
:src="`/api/Images/user/160x160/${user.id}/download?access_token=${token}`" :src="`/api/Images/user/160x160/${user.id}/download?access_token=${user.token}`"
spinner-color="white" spinner-color="white"
/> />
</q-avatar> </q-avatar>
@ -37,10 +37,18 @@
</q-menu> </q-menu>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { Options, Vue } from 'vue-class-component'; import { onMounted, computed } from 'vue';
import { Dark, useQuasar } from 'quasar';
import { useStore } from 'vuex';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
import axios from 'axios'; import axios from 'axios';
import { Dark } from 'quasar';
const quasar = useQuasar();
const store = useStore();
const router = useRouter();
const { t, locale } = useI18n();
interface UserProfile { interface UserProfile {
id: number; id: number;
@ -49,54 +57,42 @@ interface UserProfile {
token: string; token: string;
} }
@Options({}) const darkMode = computed({
export default class UserPanel extends Vue { get(): boolean {
private lang = 'es';
mounted(): void {
axios
.get('/api/accounts/acl')
.then((response) => {
this.$store.dispatch('updateUserData', response.data);
})
.catch(() => {
this.$q.notify({
message: this.$t('errors.statusUnauthorized'),
type: 'negative',
});
this.$store.dispatch('logOut');
this.$router.push('/login');
});
}
logout(): void {
this.$store.dispatch('logOut');
this.$router.push('/login');
}
get user(): UserProfile {
return this.$store.state.user;
}
get token(): string {
return this.$store.getters.token;
}
get mode(): boolean {
return Dark.isActive; return Dark.isActive;
} },
set(value: boolean): void {
set mode(value: boolean) {
Dark.set(value); Dark.set(value);
} },
});
get language(): string { const user = computed((): UserProfile => {
return this.lang; return {
} id: store.state.user.id,
username: store.state.user.username,
nickname: store.state.user.nickname,
token: store.getters.token,
};
});
set language(value: string) { onMounted(() => {
this.lang = value; axios
this.$i18n.locale = value; .get('/api/accounts/acl')
} .then((response) => {
store.dispatch('updateUserData', response.data);
})
.catch(() => {
quasar.notify({
message: t('errors.statusUnauthorized'),
type: 'negative',
});
store.dispatch('logOut');
router.push('/login');
});
});
function logout(): void {
store.dispatch('logOut');
router.push('/login');
} }
</script> </script>

View File

@ -20,7 +20,7 @@ function loadLocaleMessages(): LocaleMessages<VueMessageType> {
} }
export default createI18n({ export default createI18n({
legacy: true, legacy: false, // Disabled for composition API usage
locale: process.env.VUE_APP_I18N_LOCALE || 'en', locale: process.env.VUE_APP_I18N_LOCALE || 'en',
fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en', fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en',
messages: loadLocaleMessages(), messages: loadLocaleMessages(),

View File

@ -4,11 +4,4 @@
</q-page> </q-page>
</template> </template>
<script lang="ts">
import { Options, Vue } from 'vue-class-component';
@Options({})
export default class Customer extends Vue {}
</script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

View File

@ -4,11 +4,4 @@
</q-page> </q-page>
</template> </template>
<script lang="ts">
import { Options, Vue } from 'vue-class-component';
@Options({})
export default class Dashboard extends Vue {}
</script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

View File

@ -59,22 +59,14 @@
</q-layout> </q-layout>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { Options, Vue } from 'vue-class-component'; import { ref } from 'vue';
import Topbar from '@/components/Topbar.vue'; import Topbar from '@/components/Topbar.vue';
const drawer = ref(false);
const miniState = ref(true);
@Options({ function onToggleDrawer(): void {
components: { drawer.value = !drawer.value;
Topbar,
},
})
export default class Main extends Vue {
drawer = false;
miniState = true;
onToggleDrawer(): void {
this.drawer = !this.drawer;
}
} }
</script> </script>

View File

@ -2,11 +2,4 @@
<q-page> Page not found </q-page> <q-page> Page not found </q-page>
</template> </template>
<script lang="ts">
import { Options, Vue } from 'vue-class-component';
@Options({})
export default class NotFound extends Vue {}
</script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

View File

@ -4,14 +4,14 @@
<q-toolbar> <q-toolbar>
<q-space></q-space> <q-space></q-space>
<q-toggle <q-toggle
:label="$t(`globals.lang['${language}']`)" :label="t(`globals.lang['${locale}']`)"
icon="public" icon="public"
color="orange" color="orange"
false-value="es" false-value="es"
true-value="en" true-value="en"
v-model="language" v-model="locale"
/> />
<q-toggle v-model="mode" checked-icon="dark_mode" color="orange" unchecked-icon="light_mode" /> <q-toggle v-model="darkMode" checked-icon="dark_mode" color="orange" unchecked-icon="light_mode" />
</q-toolbar> </q-toolbar>
</q-header> </q-header>
<q-page-container> <q-page-container>
@ -24,7 +24,7 @@
filled filled
color="orange" color="orange"
v-model="username" v-model="username"
:label="$t('login.username')" :label="t('login.username')"
lazy-rules lazy-rules
:rules="[ :rules="[
(val: string) => (val && val.length > 0) || 'Please type something', (val: string) => (val && val.length > 0) || 'Please type something',
@ -35,16 +35,16 @@
color="orange" color="orange"
type="password" type="password"
v-model="password" v-model="password"
:label="$t('login.password')" :label="t('login.password')"
lazy-rules lazy-rules
:rules="[ :rules="[
(val: string) => (val && val.length > 0) || 'Please type something', (val: string) => (val && val.length > 0) || 'Please type something',
]" ]"
/> />
<q-toggle v-model="keepLogin" :label="$t('login.keepLogin')" color="orange" /> <q-toggle v-model="keepLogin" :label="t('login.keepLogin')" color="orange" />
<div> <div>
<q-btn :label="$t('login.submit')" type="submit" color="orange" /> <q-btn :label="t('login.submit')" type="submit" color="orange" />
</div> </div>
</q-form> </q-form>
</q-card> </q-card>
@ -54,88 +54,65 @@
</q-layout> </q-layout>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { Options, Vue } from 'vue-class-component'; import { computed, ref } from 'vue';
import { Dark, useQuasar } from 'quasar'; import { Dark, useQuasar } from 'quasar';
import { useStore } from 'vuex';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
import axios from 'axios'; import axios from 'axios';
interface LoginForm { const quasar = useQuasar();
username: string; const store = useStore();
password: string; const router = useRouter();
keepLogin: boolean; const { t, locale } = useI18n();
}
@Options({ let username = ref('');
setup() { let password = ref('');
return { let keepLogin = true;
$q: useQuasar(),
};
},
})
export default class Login extends Vue {
username?: string;
password?: string;
keepLogin?: boolean;
private lang = 'es';
get mode(): boolean { const darkMode = computed({
get(): boolean {
return Dark.isActive; return Dark.isActive;
} },
set(value: boolean): void {
set mode(value: boolean) {
Dark.set(value); Dark.set(value);
} },
});
get language(): string { function onSubmit(): void {
return this.lang; axios
} .post('/api/accounts/login', {
user: username.value,
set language(value: string) { password: password.value,
this.lang = value; })
this.$i18n.locale = value; .then((response) => {
} store.dispatch('logIn', {
token: response.data.token,
onSubmit(): void { keepLogin: keepLogin,
axios
.post('/api/accounts/login', {
user: this.username,
password: this.password,
})
.then((response) => {
this.$store.dispatch('logIn', {
token: response.data.token,
keepLogin: this.keepLogin,
});
this.$q.notify({
message: this.$t('login.loginSuccess'),
type: 'positive',
});
this.$router.push('/dashboard');
})
.catch((error) => {
const errorCode = error.response.status;
if (errorCode === 401) {
this.$q.notify({
message: this.$t('login.loginFailed'),
type: 'negative',
});
} else {
this.$q.notify({
message: this.$t('errors.statusInternalServerError'),
type: 'negative',
});
}
}); });
}
data(): LoginForm { quasar.notify({
return { message: t('login.loginSuccess'),
username: '', type: 'positive',
password: '', });
keepLogin: true, router.push('/dashboard');
}; })
} .catch((error) => {
console.log(error);
const errorCode = error.response.status;
if (errorCode === 401) {
quasar.notify({
message: t('login.loginFailed'),
type: 'negative',
});
} else {
quasar.notify({
message: t('errors.statusInternalServerError'),
type: 'negative',
});
}
});
} }
</script> </script>