Aurelia Multi-page App? - url-routing

If I have main.ts file setup like so...
Main.ts
import {Aurelia} from 'aurelia-framework'
import environment from './environment';
//Configure Bluebird Promises.
(<any>Promise).config({
warnings: {
wForgottenReturn: false
}
});
export function configure(aurelia: Aurelia) {
aurelia.use
.standardConfiguration()
.feature('resources');
if (environment.debug) {
aurelia.use.developmentLogging();
}
if (environment.testing) {
aurelia.use.plugin('aurelia-testing');
}
// PLAYING AROUND - Log to Console the Value of ShowLanding Session Storage
let showLanding = false;
console.log(showLanding);
// let showLanding = sessionStorage.getItem("show_landing");
if (showLanding || showLanding === null) {
aurelia.start().then(() => aurelia.setRoot('landing'));
} else {
aurelia.start().then(() => aurelia.setRoot('blog/blog'));
}
}
I have a "Landing.html/.ts" file in the root of my app, and this bit of code seems to work well. Meaning, if "showLanding = false" the app will load to my "blog.html" page, and if it's true, it will load to my "Landing.html" page.
What I'm trying to do is create an Admin page. Anytime URL is visited "....com/admin" take me to "admin.html" page I have setup.
Is that possible to do front-end? Only other way I know would be to match URL and static-serve from server route, yeah?

I managed to get this working (the way I wanted it to work) by just simply reading window.location.pathname and setting my admin page as app root.
so my Main.ts was changed to:
...
if (showLanding || showLanding === null) {
aurelia.start().then(() => aurelia.setRoot('landing'));
} else if (window.location.pathname == "/admin") {
aurelia.start().then(() => aurelia.setRoot('admin/admin'));
} else {
aurelia.start().then(() => aurelia.setRoot('blog/blog'));
}
}
I'm sure this probably isn't the best way to accomplish this, but it seems to be working for now. I'll be sure and update this if there are any issues I run into.
Also, if someone else wants to chime in with any alternative thoughts, concerns, suggestions, or feedback, please do! Thanks!

Related

How do I break the infinite redirect loop I've created in Next JS?

This application is being hosted on S3, entirely static (using next export), and we're routing all 404 errors to index.html in order to let those be handled on the client side so we can take advantage of dynamic routing. To handle this, I have the following in my _app.tsx file:
const { asPath, pathname, ...router } = useRouter();
// check if redirect
React.useEffect(() => {
if (pathname === '/' && asPath !== pathname) {
router.replace(asPath, undefined, { shallow: true });
}
}, [asPath]);
This works, for the dynamic routing aspect, but it introduces a new bug: when I navigate to a page that actually doesn't exist, like /fffff, there's an infinite loop of the app trying to reroute to /fffff. Ideally, it would only try to reroute once, and then default to the 404.tsx or _error.tsx page. I've tried creating a stateful boolean like hasRedirected and then just marking that as true in the useEffect, but that didn't work because the page is actually refreshing and thus resetting state on each router.replace call. How do I handle this error and break out of the loop?
update: The issue seems to be that when I call router.replace, Next doesn't find a path to match /fffff, so its default behavior is to try asking the server for the route by refreshing. I need to disable or intercept this behavior somehow.
The solution we ended up finding, which works quite well, uses session storage to store a hasRedirected variable that gets deleted after being read. Here's the code:
React.useEffect(() => {
if (router.isReady) {
const isRedirect = pathname === '/' && asPath !== pathname;
if (sessionStorage.getItem('hasRedirected')) {
sessionStorage.removeItem('hasRedirected');
if (isRedirect) router.replace('/404');
} else if (isRedirect) {
sessionStorage.setItem('hasRedirected', 'true');
router.replace(asPath);
}
}
}, [asPath, pathname, router.isReady]);

MSAL setActiveAccount from within function

So I'm in the process of setting up MSAL with AAD for my react project. As it is, everything is working as expected, I can login, refresh the page (to get the latest active token) and logout.
However, as I was trying to refactor some of my code to make it more readable, I ran into a problem with setActiveState(), the following code works in my App.js:
export const msalInstance = new PublicClientApplication(msalConfig);
const accounts = msalInstance.getAllAccounts();
if (accounts.length > 0) {
msalInstance.setActiveAccount(accounts[0]);
}
However, I wanted to refactor the above as follows - To handle more cases in a joint function:
export const msalInstance = new PublicClientApplication(msalConfig);
function handleResponse(response) {
if (response !== null) {
const accountId = response.account.homeAccountId;
} else {
const currentAccounts = msalInstance.getAllAccounts();
if (currentAccounts.length === 0) {
// no accounts signed-in, attempt to sign a user in
instance.loginRedirect(loginRequest);
} else if (currentAccounts.length > 0) {
msalInstance.setActiveAccount(currentAccounts[0]);
}
}
}
msalInstance.handleRedirectPromise().then(handleResponse);
The above code is capable of getting all current accounts and it successfully reaches setActiveAccount, however nothing happens - I.e. my active account is not being set, which means that my <AuthenticationTemplate/> is stuck loading.
Please double-check your application, tenant, and client identifiers. Also, make sure that http://localhost:3000 is listed among the Allowed Web Origins in Azure's Application settings.
Check out this sample for further guidance.

Import NPM package only for server side rendering(SSR) in Next.js App

I am trying to use one private NPM module only when the page is loading for the first time and rendering is happening on the server. I am using the following piece of code but I am still able to see my package in chunks in client.html using the build analyzer.
if (typeof window === 'undefined') {
const content = await import('#abc/my-npm-package');
return conent(payload);
} else {
return null;
}
Excellent question, I've poked around the Next.js's code and found out that in order to code that will be exists only on the server you need to use some variable which is passed to webpack.DefinePlugin (which at build time will replace the usage with the value, this what allows the tree-shake to work).
From this line, there is a special variable process.browser which will be true only in the browser.
Change your code to
if (!process.browser) {
const content = await import('#abc/my-npm-package');
return conent(payload);
} else {
return null;
}
Update 16.03.2022
Next.js will deprecate process.browser soon, the new recommended way to distinguish between client & server is by checking type of window === 'undefined' // means that it's server side.
if (typeof window === 'undefined') { // server side
const content = await import('#abc/my-npm-package');
return content(payload);
} else { // client side
return null;
}

react native geolocation not asking user permission on android emulator

Hi Im using the below code to successfully get user location, but in the android emulator it is not asking user if they want to share their location (even after I reinstall the app).
The code works which is great....but I really would like the standard alert to appear which says "are you sure you want to share your location with the app"
Any guidance would be appreciated
navigator.geolocation.getCurrentPosition(
(pos) => {
console.log(pos.coords.longitude, pos.coords.latitude);
I think location permission not show again event you reinstall app because phone still remember permissions granted for app. You can check app have permission granted in Android Setting with App (https://www.howtogeek.com/230683/how-to-manage-app-permissions-on-android-6.0/).
Maybe this code can help you
import { PermissionsAndroid } from 'react-native';
async function getLocation() {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
'title': 'App',
'message': 'are you sure you want to share your location with the app ?'
}
)
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
// permission granted
// do code get location here.
navigator.geolocation.getCurrentPosition(
(pos) => {
console.log(pos.coords.longitude, pos.coords.latitude);
})
} else {
// permission denied
console.log("GPS permission denied")
}
} catch (err) {
console.warn(err)
}
}

How to resolve an url by fetch & redirect without refresh with react

I need to fetch the current url in my react application because our front/nginx may respond with a redirect which won't be hit if user has the service-worker active..
therefor I currently have this logic in my 404 component on didMount.
fetch('/test/page/xxxx/', {redirect: 'follow'}).then(res => {
if(res.status === 200 && res.redirected) {
console.log(res)
// this.props.push(res.url)
// window.location.replace(res.url)
// window.location.hash = res.url
console.log('Redirected to ' + res.url)
}
})
the res.url that I get back in the respons is a full url ex: https://example.net/xxx/xxx/xxxx which makes it hard for me to use push from react-router-redux because it expects a relative url. Can anyone help me with a regex that can get the slugs from the res.url or does anyone have any other idea how to solve this problem?
There is the URL interface [1] available in the window that can be used create a URL object.
A URL object has the pathname property that is used to retrieve the path component of the URL.
this.props.push(
new URL(res.url).pathname
)
The easiest way to get the pathname (relative URL) is by parsing it with the URL interface API
const { pathname } = new URL("https://example.net/aaa/bbb/ccc");
console.log(pathname) // "/aaa/bbb/ccc"
In the context of your code
fetch("/test/page/xxxx/", { redirect: "follow" }).then(res => {
if(res.status === 200 && res.redirected) {
const { pathname } = new URL(res.url);
this.props.push(pathname);
}
});
NOTE: Not supported in IE11 and below. If support for that browser is needed, there is a polyfill https://github.com/lifaon74/url-polyfill
There is also a proposal to be added to babel, expected soon to be a stage 0 feature

Resources