Change body class when it has aurelia-app attached - aurelia

Shortly I have two shells/roots: one for login page and one for the rest of the application and switch between them given the user is logged in or not.
My aurelia-app is attached to body element but I have distinct body classes for login and the rest of the application.
What is the best way to also switch body classes depending on the active shell?

In my opinion, the easiest way is changing the body class in the main.js file. For instance:
let rootComponent = '';
aurelia.start().then(a => {
if (!app.isLoggedIn()) { //<--- example of func to check if the user is logged in
document.body.className = "example-class-1";
rootComponent = 'login/login';
} else {
document.body.className = "example-class-2";
rootComponent = 'app/app';
}
a.setRoot(rootComponent, document.body);
});
Hope this helps!

Related

Vue, wait data is assign to run a function

I have a method in my Vue instance that do the following:
submitForm(confirmation) {
//set price confirmation
this.price_confirmation = confirmation
//proceed
var form = this.getForm()
}
Price confirmation is the v-model of an input.
Then the method getForm serialize (with jquery) the form. The thing is that my form is being serialized before this.price_confirmation = confirmation is run.
How can I run this.getForm() after Vue assign the data?
You probably need to use the nextTick method to wait until the next update cycle:
submitForm(confirmation) {
//set price confirmation
this.price_confirmation = confirmation
//proceed
this.$nextTick(() => {
var form = this.getForm();
});
}
From what you've shared, it's not clear how the confirmation is set in your component and at what point the submitForm is called. submitForm method seems to be correct, and should work correctly (i.e. this.getForm() is called after this.price_confirmation is set). What you could do is, look where the confirmation variable is set and add an async function to it. e.g:
async confirmation() {
await getConfirmations();
}
If you need more help please share the relevant code from your component.

Getting requested page route in Nuxt middleware

I have a very simple 'named' Nuxt middleware set up (taken from the docs) which checks in the store to see whether a user is authenticated before they can navigate to certain routes. If the user is not authenticated, they are directed to a straightforward form in which they have to provide an email address to gain access (at http://example.com/access). All of that works fine, after they fulfil the middleware's store.state.authenticated check they can navigate around no problem.
export default function ({ store, redirect }) {
if (!store.state.authenticated) {
return redirect('/access')
}
}
My question is, once the user has entered their email address, I have no way of knowing what route they were initially trying to access. I've looked at other questions here about passing data between routes but because of the way the middleware works these solutions don't seem to be feasible.
I really would rather not set the slug in the vuex state as this will lead to a whole other set of complications – I also don't mind setting the intended slug as a query or a param on the /access url. I have read through the docs for the Nuxt redirect function and realise you can pass a route.query as an argument. So it seems that you could potentially do something like this:
return redirect('/access', intendedSlug)
...or, if using params(?):
return redirect(`/access/${intendedSlug}`)
But I don't know how to pass that intendedSlug value to the middleware in the first place as it's not exposed on the context passed to the function or anywhere else. It seems like this would be a common problem, but I can't find any simple solutions – any help would be really appreciated!
To help #Bodger I'm posting how I resolved this, it may not be perfect and it's working on a slightly older version of Nuxt (I know 😵!) but this is how I resolved the issue.
.../middleware/authenticated.js
export default function (context) {
const path =
context.route.path.length && context.route.path[0] === '/'
? context.route.path.slice(1)
: context.route.path
const pathArray = path.split('/')
if (process.server && !context.store.state.authenticated) {
return context.redirect('/access', pathArray)
} else if (!context.store.state.authenticated) {
return context.redirect('/access', pathArray)
}
}
The pathArray is then accessible in my /access page.
.../pages/access.js
data() {
return {
attemptedRoutePathArray: Object.values(this.$route.query)
...
}
},
...
computed: {
attemptedRouteURL() {
return new URL(
this.attemptedRoutePathArray.join('/'),
process.env.baseUrl
)
},
...
}

Determine if opened as dialog in prompt

I am developing an aurelia app. I have a component (which is a full-page component and is navigable) and also in another page, I want to use this component as a prompt to let user choose from that page. So I have written the code below to open it as intended:
selectTaskFromTree(callbackOrSuccess, failure) {
const dialog = this.dialogService
.open({ viewModel: PLATFORM.moduleName('features/view/tree/tree'), model: {}, lock: false });
if (callbackOrSuccess) {
if (failure) {
dialog.whenClosed(response => {
if (!response.wasCancelled) {
callbackOrSuccess(response.output);
} else {
failure(response);
}
});
}
else{
dialog.whenClosed(callbackOrSuccess);
}
return;
}
else{
return dialog;
}
}
So the component Tree is now successfully loaded and shown. The problem is now how to determine if the TreeComponent is opened as a dialog or not.
The way I am thinking about is to pass an arbitrary param to it and if the param is true, the status is dialog and otherwise not dialog:
const dialog = this.dialogService
.open({ viewModel: PLATFORM.moduleName('features/view/tree/tree'), model: {isDialog: true}, lock: false });
But I think maybe there is also a better way to do this. For example to ask from DialogService if I am a dialog or not. So what are the other solutions and which one is better?
To determine whether or not you have an open (or active) dialog you can ask DialogService for the relevant fields:
this.dialogService.hasOpenDialog
this.dialogService.hasActiveDialog
Sadly, this cannot tell you which dialog is open. I would argue that your idea of passing a param to the model is an equally valid way of doing it.
I have thought about different solutions and I was seeking for keeping coupling low and preventing define of new param. So I wrote the below code where I want to know if this component is opened as a dialog or not:
attached() {
this._isDialog = Boolean(this.dialogController.settings);
}

Current user doesn't persist when reloading an app (Ionic2 + Parse Server)

I'm currently working on Ionic 2 app with Parse Server backend.
I implemented signed up process. No problems here, everything works as expected: new account is created, user is logged in after sign up and current user exists.
Now I want to use current user and bypass sign up/login page next time user opens the app (if the user is already logged in ). The Parse documentation clearly states:
“It would be bothersome if the user had to log in every time they
open your app. You can avoid this by using the cached
current Parse.User object. Whenever you use any signup or login
methods, the user is cached in localStorage.”
In my case, however, I can't manage to make it work. I create current user according to Parse documentation during initialization process of the app:
var currentUser = Parse.User.current();
if (currentUser) {
// do stuff with the user
} else {
// show the signup or login page
}
Every time I open the app after successful sign up the current user is NULL.
Any ideas?
I kinda understand what's going on, but still don't understand why.
During signup or login Parse is supposed to save current user to local storage, but if local storage is not available for some reason, it saves it to memory map. And this is what happens in my case: Parse always saves current user to memory map, which is, of cause, temporary storage. Hence, every time I reload the app, Parse memory map is empty. I don't understand why in my environment Parse decides that local storage is unavailable. I couldn't find in the code where this decision is made. It seems to me that memory map is default (which is probably not true). Could it be that local storage functionality is not implemented yet in the open source version of Parse? Or does it have something to do with Ionic2 implementation?
Is there anybody out there from Parse team who is familiar with this part of Parse code?
Thanks.
Hi I use Local Storage.
import { Component } from '#angular/core';
import { NavController,Alert,Storage,LocalStorage } from 'ionic-angular';
import {HomePage} from'../home/home';
import {UserdetailPage} from'../userdetail/userdetail';
declare var require:any;
var Parse = require('parse/node');
#Component({
templateUrl: 'build/pages/user/user.html',
})
export class UserPage {
public currentUser:any;
public local:any;
username:string="";
password:string="";
repassword: string="";
sign:string = "SIGN IN";
constructor(private nav: NavController) {
Parse.initialize(XXXXX);
Parse.serverURL = 'XXXXXX';
this.local = new Storage(LocalStorage);
this.currentUser = this.local.get('userid');
console.log(this.currentUser);
}
signin(){
console.log("username:"+this.username);
console.log("password:"+this.password);
if(this.username!="" &&this.password!=""){
if(this.repassword!=""){
// Register User Session
this.register();
}
else if(this.repassword==""&&this.username!=""&&this.password!=""){
this.login();
}
}
}
changeSign(s:string){
console.log(s);
if(s!="")
this.sign = "SIGN UP (Register New Account)";
else
this.sign ="SIGN IN";
}
register(){
if(this.repassword==this.password){
var parseuser = new Parse.User();
parseuser.set("username",this.username);
parseuser.set("password",this.password);
parseuser.signUp(null, {
success:user=>this.registerSucessAlert(),
error: error=>this.registerFailAlert("Register Fail, The user name exists or Server is down")
});
}
else{
this.registerFailAlert("Password is not the same");
}
}
login(){
console.log("Login");
Parse.User.logIn(this.username, this.password, {
success:user=>this.loginSucessAlert(),
error:error=>this.loginFailAlert()
});
}
loginSucessAlert(){
this.currentUser = Parse.User.current().id;
this.local.set('userid',this.currentUser);
let alert = Alert.create({
title:'Login',
subTitle:'Hi '+this.username+', Press to Continue.',
buttons:[{text:'OaaaK',
handle:()=>{this.nav.setRoot(UserdetailPage);}}]
});
this.nav.present(alert);
}
loginFailAlert(){
let alert = Alert.create({
title:'Login',
subTitle:'Login Error',
buttons:['OK']
});
this.nav.present(alert);
}
registerSucessAlert(){
this.currentUser = Parse.User.current().id;
this.local.set('userid',this.currentUser);
let alert = Alert.create({
title:'Resgiter',
subTitle:'Thank you'+this.username+' for register, Press to Continue.',
buttons:['OK']
});
this.nav.present(alert);
}
registerFailAlert(err:string){
let alert = Alert.create({
title:'Register Fail',
subTitle:err,
buttons:['OK']
});
this.nav.present(alert);
}
}

OpenTok - How to publish/unpublish manually?

I looked at these links
http://www.tokbox.com/opentok/api/tools/js/documentation/overview/publish.html
http://www.tokbox.com/opentok/api/tools/js/tutorials/overview
but their are no examples for publishingunpublishing manually, that is, publishing/unpublishing without using 'streamCreated'/'streamDestroyed' event handler respectively.
The reason I want to do this is that I have a button to publish/unpublish so that the user can do it at will.
Is there a way to do this?
Yes and it is very simple. Check out the prepublish source code to see how. There are 2 functions, startPublishing() and stopPublishing() which achieve this.
Primarily they use session.publish(publisher);to publish and session.unpublish(publisher); to unpublish.
Here is code I have used to work off:
// Called by a button to start publishing to the session
function startPublishing() {
if (!publisher) {
var parentDiv = document.getElementById("myCamera");
var publisherDiv = document.createElement('div'); // Create a div for the publisher to replace
publisherDiv.setAttribute('id', 'opentok_publisher');
parentDiv.appendChild(publisherDiv);
var publisherProps = {
width : VIDEO_WIDTH,
height : VIDEO_HEIGHT
};
publisher = TB.initPublisher(apiKey, publisherDiv.id, publisherProps); // Pass the replacement div id and properties
session.publish(publisher);
show('unpublishLink');
hide('publishLink');
}
}
//Called by a button to stop publishing to the session
function stopPublishing() {
if (publisher) {
session.unpublish(publisher);
}
publisher = null;
show('publishLink');
hide('unpublishLink');
}