Where is the state of a Electron-Vue application stored? - vue.js

How and, more to the point, where is state data persisted between sessions?
I followed this tutorial (https://alligator.io/vuejs/vue-electron/) to create a simple ToDo App using Vue.js in Electron.
After filling in some blanks everything works. However, I'm unable to find where the application state is stored. For example, in Dev mode (npm run dev), if I add some ToDo items and then close the App (and even restart VS Code) the ToDo data is persisted when the App is restarted.
I'm using Win10 and, among other things, have tried searching for files changed within the last 30 minutes (datemodified:‎23/‎09/‎2019 12:30..13:00) but without luck. I've looked in my profile, the App directory, and searched google for clues.
[Edit]
I think it has something to do with this import { createPersistedState, createSharedMutations } from 'vuex-electron' (located in src\renderer\store\index.js) but not much closer to understanding where the state is stored. Yep - I'm pretty new to this.
For what it's worth, if you want to follow this tutorial:
Issue 1.
Now that we know how the Vue application is started, let’s take a look at the defined routes within our application. Head over to src/router/index.js:
should be: src/renderer/router/index.js:
Issue 2. In src/renderer/components/LandingPage.vue
<div class="todos">
<ul>
<li
class="todo-item"
v-for="todo in todos"
:key="todo.id"
#click="completeTodo(todo)"></li>
</ul>
</div>
should be:
<div class="todos">
<ul>
<li
class="todo-item"
v-for="todo in todos"
:key="todo.id"
#click="completeTodo(todo)">{{todo.name}}</li> // {{todo.name}}
</ul>
</div>

Using 'createPersistedState' option of 'vuex-electon' saves in json format in 'AppData' path.
uerName/AppData/Roaming/Electron/vuex.json
Remove 'createPersistedState' to disable saving.
import { createSharedMutations } from 'vuex-electron'
export default new Vuex.Store({
modules,
plugins: [
createSharedMutations()
],
strict: process.env.NODE_ENV !== 'production'
})
see a https://github.com/vue-electron/vuex-electron

Related

How to properly load Bootstrap5's Masonry into Nuxt?

I am trying to use the Masonry plugin with Bootstrap5 and NuxtJS. When I follow the example here
https://getbootstrap.com/docs/5.0/examples/masonry/ and incorporate it into my own codesandbox, I notice that my demo is not in the correct masonry format. See the gaps? My sandbox
My example:
Bootstrap's example:
What do I need to do to get my demo into format shown on the Bootstrap Masonry example page?
I checked how to load the script from a CDN either globally or locally. It was working but at one condition: you needed to NOT start on the masonry page.
Meaning that if you loaded the app on a specific page, then moved to the one with the masonry it was working. But not if you started on this specific page. So, a pretty subpar solution.
This article was really helpful to understand how to wait until the CDN script is fully loaded: https://vueschool.io/articles/vuejs-tutorials/how-to-load-third-party-scripts-in-nuxt-js/
Then I realized that we are far better installing it directly as an NPM dependency. Therefore, I proceeded to the masonry repo. Found a great message on how to setup the whole thing in Nuxt.
And after a removal of some useless stuff and some modern dynamic import, here we are
<template>
<main>
<h1>Bootstrap and Masonry</h1>
<div class="row" id="masonry">
<!-- ... -->
</main>
</template>
<script>
export default {
async mounted() {
if (process.browser) {
let { default: Masonry } = await import('masonry-layout')
new Masonry('#masonry', { percentPosition: true })
}
},
}
</script>
The final solution is looking pretty well and there is not a lot of code. On top of that, the code is properly loaded. And you can load it on a click or any other event.

Whats the simplest and proper way to route in a template

Instead of showing data from a component, I'm currently routing a user to login at /account if they are not authorized, by doing this:
<template>
<q-card v-if="authorized">
<q-card-section>
<DataGrid/>
</q-card-section>
</q-card>
<span v-else>
{{ this.$router.push('/account') }}
</span>
</template>
It's simple and works, but I'm not sure its really correct because although it pushes the user to where I want them to be, the console gets this error:
uncaught exception: undefined
(I'm currently on Quasar v1.9.14)
Basically I want to show the data if the user is authorized or redirect if they are not authorized, or become unauthorized later.
first of all, you do not need to use this in the template.
If you want to route them based on the authorized value, you could probably use a watcher.
Alternatively, I would probably do something in mounted which checks if the user can be there. E.g.
async mounted ()
{
const authorized = await fetch("something")
if (!authorized)
{
this.$router.push('/account')
}
}
Its simpler than I thought. I believe the answer is events. The span can simply change to:
<span v-else #load="$router.push('/account')"/>
<span v-else :class="authorized ? '' : $router.push('/account')"/>
Its even simpler because its a one liner
It will work even after mounted() has already fired and authorized becomes false
Actually, I now can delete similar logic in mounted() (DRY principle)
EDITS:
After proper testing I found it actually does not work with my first #load event example.

Vue rendering only part of my App.vue after a login

I am working on a Vue.js application that I am almost done, one major bug left. The bug/issue is that when you go to /login and login to the site you get redirected via a router push (tried replace too) and when this happens I want to render the whole dashboard. Currently since in my App.vue file the router view is a different part it only renders the dashboard info part and not my header or sidebar.
Pretty much imagine a dashboard without a header or sidebar. That's what's rendering. I'd be okay if I could do something like F5 does because then it all would load correctly though taking up to 2 seconds longer on login which is okay by me.
My App.vue file template code
<template>
<div class="fade page-sidebar-fixed page-header-fixed show page-container" v-if="!pageOptions.pageEmpty" v-bind:class="{
'page-sidebar-minified': pageOptions.pageSidebarMinified,
'page-content-full-height': pageOptions.pageContentFullHeight,
'page-with-top-menu': pageOptions.pageWithTopMenu,
'page-sidebar-toggled': pageOptions.pageMobileSidebarToggled,
'has-scroll': pageOptions.pageBodyScrollTop
}">
<Header />
<Sidebar v-if="!pageOptions.pageWithoutSidebar" />
<div id="content" class="content" v-bind:class="{ 'content-full-width': pageOptions.pageContentFullWidth, 'content-inverse-mode': pageOptions.pageContentInverseMode }">
<router-view></router-view>
</div>
</div>
<div v-else>
<router-view></router-view>
</div>
</template>
Looks like I have resolved my issue, it comes from vue-router and how I am doing that if statement in my template code. So in that code I am checking a boolean value then choosing which view to render. So I had though on all of my auth pages I set the value correctly on exit. Turns out not...
This was in my Login.vue file, idea was to have on an exit of the route that it would change the boolean to false which would let me render it right. This was something I did initally but had forgotten about till about 20 minutes ago.
Upon checking this I found the value was not being changed for some reason. So as a work around in the created part of my Dashboard.vue file I set the value to false explicitly
Login.vue
beforeRouteLeave (to, from, next) {
PageOptions.pageEmpty = false;
next();
},
Dashboard.vue
created() {
PageOptions.pageEmpty = false;
...
}
The main idea is to have several base pages each one of them is operate with its own set of internal views.
You have to redirect user to another view, which is the one and only active view and this view can contains sidebar header and main part that also contains router-view, and then! you load any needed components in it.
You have to have something like that:
App component is only contains router view tag and any other pages are load into this.
The routes structure then looks like that:
As you can see, there are two base views load in App view. And then the base view can has a lot of children. The level of nested routes is up to you. Here is the contents of my app Home view:
And the MainContent component which is contains router view only:
The good example of project structure is the one generated with vue-cli. You can use it to simplify dev process with a lot of benefits and good practice solutions.

VueJS in Blade Template without Build Step

I'm trying to implement VueJS in one of my pages blade template. I just want to use Vue in that single template.
I tried the following:
default.blade.php
//...
#yield('js-for-layout-before')
<script src="{{ asset('js/vue.min.js') }}"></script>
// ...
view.blade.php
#extends('layouts.default')
//...
#section('content')
<div id="app">
<ol>
<todo-item></todo-item>
</ol>
<p>#{{ message }}</p>
</div>
<script type="module" src="{{ asset('js/pages/vue_component.js') }}"></script>
#stop
vue_component.js
Vue.component('todo-item', {
template: '<li>This is a list item</li>'
})
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
})
With this, I am only getting a blank page. There are no errors in the console, all files are loaded.
The inspector shows what I mean:
I do not want to implement a build step or anything, just a minimum setup with vue. Any ideas what I am missing here?
--UPDATE:
I replaced vue.min.js with the development version and finally got a clue:
vue.js:633 [Vue warn]: It seems you are using the standalone build of
Vue.js in an environment with Content Security Policy that prohibits
unsafe-eval. The template compiler cannot work in this environment.
Consider relaxing the policy to allow unsafe-eval or pre-compiling
your templates into render functions.
For reference, the issue was that my CSP didn't allow for unsafe-eval, which is required in this scenario without a build step. I didn't notice this until I included vue.js instead of the minified vue.min.js, which doesn't show errors.
To fix this for now, I did the following, though you should probably not do this in production: Check where your CSP is defined and add 'unsafe-eval' to "script-src".
In production, you probably want to use nonce on the script instead of unsafe-eval and something like https://github.com/spatie/laravel-csp to generate the nonce.

anchor is not redirecting to display inside ng-view, rather reloading with new page

I wrote a simple angular application in a learning purpose. However the controllers are working in my system but not in plunker. But, that is not my concern. My concern is I am unable to see the linked pages inside ng-view. They are rather opening as a new page replacing the home page. Secondly, the expressions are not reflecting their values. Kindly help me out. I have uploaded the codes in plunker.
Link to Plunker
<div ng-controller="RamFirstCtrl">{{name}}</div>
<div ng-include="'navbar-top.html'"></div>
<div style="border:1px solid green; position:relative;" ng-view></div>
Noticed couple thing:
http to https, there is error in console, it might be the reason it doesn't work in plunker
<script src = "https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.js"></script>
you have to use the url define in your router:
ng-href="aboutUS.html" to ng-href="#!/aboutUS"
.when("/aboutUS", {
templateUrl : "aboutUS.html"
})
<div>
<a ng-href="#!/aboutUS">
AboutUs
</a>
</div>
Note:#! will be added to url by angular router by default