WHMCS how can I conditionally hide the primary navigation bar on the top of the client pages? - whmcs

I am developing a web site selling web hosting and domain registration so I am using WHMCS but I am facing a problem I want to make a custom page under WHMCS directory to allow the admin user to change product's details without showing the top navigation bar which created by WHMCS.

Not sure by Admin user, but if you mean you want to remove the primary menu from client area, add this code to a php file inside: whmcs_dir/includes/hooks (say nomenu.php)
add_hook('ClientAreaNavbars', 1, function ()
{
// Get the current navigation bars.
$primaryNavbar = Menu::primaryNavbar();
$secondaryNavbar = Menu::secondaryNavbar();
$children = $primaryNavbar->getChildren();
if (!is_null($children)) {
foreach ($children as $child) {
$primaryNavbar->removeChild($child);
}
}
$children = $secondaryNavbar->getChildren();
if (!is_null($children)) {
foreach ($children as $child) {
$secondaryNavbar->removeChild($child);
}
}
});
Also, add css code to hide the menubar remaining after removing the items:
#main-menu {display: none}
One note though: even if you hide the menu items, if logged in user knows the page link, which is not secret, he can type the URL directly in the address bar to visit it.
For example, to access my domains page in whmcs: http://whmcs-url.com/clientarea.php?action=domains
Your option to have better control is to check the API functions.

Related

Is it possible to change url using vue-router without going to the page?

There is a shop on nuxtjs and on the /catalog page I need to make a "Load more" button. By clicking on it, products should be loaded and the url should be changed to /catalog/page_2 (?page=2 is not suitable).
If I change the url through $router.push nuxt goes to this page, but I need to change the url, but not go anywhere.
Is it possible to somehow undo the reloading but save the changes in the url?
history.pushState copes with the task, but in this case nuxt does not know that the url has changed and when clicking forward / backward in the browser nuxt does not load the goods needed for this page
Paginations logically belong to the main page so It's good to consider them in URL queries, like ?page=2.
also you can use router.replace to change queries.
this.$router.replace({
query: { ...this.$route.query, page: this.page},
})
Do it with this example
https://codesandbox.io/s/withered-darkness-9ezn9?file=/pages/index/_id.vue
Now I can change the filters, categories, and the url changes, but the page does not reload
As you don't want to change the page if you are already on the correct one, check for differences in current page URL first;
const your_query = '?page=2' // containing url params
const currPath = this.$route.fullPath; // containing current path + query params, e.g. '/catalog/?page=2'
const nextPath = `${this.$route.path}?${your_query)}`;
if (currPath !== nextPath) {
//"Abuse" router to change the current's windows url
this.$router.replace(nextPath, undefined, () => {
//If route navigation fails, e.g. due to a same-route navigation or wrong permissions in navigation-guards, handle here
return;
});
}
Alternative would be to directly pass the new query params to the router, as:
this.$router.replace({ query:
page: 2
})

Filling form fields of a webpage opened in a web view with React Native

I'm working on a project that includes a module that helps with electricity recharge, so what happens is that the user's data is already saved in the app and when they choose to recharge, the app opens up this webpage in a web view.
Currently, I'm using WebBridgeView for opening the webpage as:-
render() {
return (
<WebViewBridge
ref="webviewbridge"
onBridgeMessage={this.onBridgeMessage.bind(this)}
source={{uri: "https://currencypin.com/PrepaidMeterPaymentsV2.0/cartwiz?c=IN&p=5&pm=tm"}}/>
);
}
}
Now, what I want is that when the webpage opens, the form fields come prefilled with the custom data that I have. So that the only field that the user needs to fill on the page is the CAPTCHA.
I was following this article for achieving the same, but it actually assumes that the website is customizable. Which is not possible in my case because it belongs to a 3rd party vendor.
What are the ways to achieve this?
You have to use the injectedJavaScript prop from WebView.
First declare a jsCode variable:
const amount = 2
const jscode = `
if (document.getElementById('txtAmount') == null) {
// field not existing, deal with the error
} else {
document.getElementById('txtAmount').value = '${amount}';
}
`
Please notice the " ` " character. Used to put variables in strings.
Then use it like so:
<WebViewBridge
ref="webviewbridge"
onBridgeMessage={this.onBridgeMessage.bind(this)}
injectedJavaScript={jsCode}

How to create standalone custome page?

I'm looking for a way to create single page model/ standalone single page.
It's like a custom single page for 'About Us', 'Home Page','Our Team',etc.
They are single page with backend options.
Anyone have any idea ?
So you need to create all needed type of files, like route JS file, template file, add info about that file into routes/index.js
example:
create file routes/views/aboutUs.js :
var keystone = require("keystone");
exports = module.exports = function(req, res) {
var view = new keystone.View(req, res);
var locals = res.locals;
// locals.section is used to set the currently selected
// item in the header navigation.
locals.section = "about-us";
locals.title = "About our company";
// Render the view
view.render("aboutUs");
};
create template file templates/aboutUs.pug :
block content
p Our company is super cool. We based it here long time ago
Put all your static content into template with correct syntax and css
Finally make addition to routes/index.js file:
app.get("/aboutUs", routes.views.aboutUs);
if you need to control user access to page also add such string
app.all("/aboutUs*", middleware.requireUser);
And dont forget to restart the app to see changes
That's clearly not what OP is asking for. They're asking if there is a way to create a single ADMIN UI editable page for Home, About Us, and so on. My answer is that I don't believe that is possible with KeystoneJS. Which is annoying, because I have clients that want that and Keystone would be perfect otherwise. Seems the only way to do it is create a list, auto create a record if one doesn't exist, and set "nocreat", and "novelette" on the list.

Allow Administrators to impersonate users using an iframe

I have an MVC project with three roles: Users, Account Managers, and Administrators.
Administrators have their own MVC Area where they have full control over Users and Account Managers. I'm trying to implement functionality to allow Administrators to view the site as any User or Account Manager.
In the Admin Area of the site, I have a View of a list of Users and Account Managers. The list contains a "View Site As User" button for each record.
I have never done anything like this before, but the ViewAs Controller Action is currently set up to create a Session with the selected User's information, like so:
ViewBag.SiteSession = Session["SiteSession"] = new SiteSession()
{
ID = user.ID,
AccountID = user.AccountID,
DisplayName = user.DisplayName,
IsManager = user.IsAdmin,
IsAdmin = false
};
The View relevant to this Action has the Model defined as a string, and nothing else but an iframe with the Model as the src attribute, like so:
#model string
<iframe src="#Model" >
</iframe>
What I'm trying to do is render whichever portion of the site was requested in this iframe. When an Administrator clicks "View As User," I'd like to direct to Home. The URL is generated through this call:
Url.Action("Index", "Home", new { Area = "" }));
The Area is set to nothing to avoid rendering the Admin Area's Home.
Currently, this is not working. I don't know where to even begin, minus what I already have.
I'm looking for any suggestions. All help is greatly appreciated, as this doesn't seem like an easy task.
If you don't know how to help, it would also be appreciated if you could direct this question to somebody that can.
Again, thanks in advance.
The way that I've done this in the past has been to use the concept of an an actual user and an effective user. Most display actions use the effective user to generate their content. Typically I've implemented it as "impersonation" rather than "preview" so the user is actually navigating the site as the user rather than displaying in a separate window. In this case I simply set both in the current session. Things that require admin permission (like switching to/from impersonation) obviously use the real user.
If you wanted to do preview then I'd think about using a parameter on each request to set the effective user. The code would need to understand to add this parameter to all links so that you could navigate in the iframe without messing up navigation in the original interface.
As for removing the area from the url, I think what you have (setting to the empty string) should work. If it's not working you might want to try lowercase area, Url.Action("Index", "Home", new { area = "" }). I'm pretty sure that the RouteValueDictionary that gets created under the hood uses a case insensitive key comparison, though, so it shouldn't matter.
For this task, I ended up creating a separate controller, ViewAsController, which had a controller-wide [Authorize] attribute that only allowed users with the Admin role to access its actions.
In the Start action, a Session object containing the selected User's information is created, like so:
[HttpGet]
public ActionResult Start(int id)
{
var user = db.Users
.First(u => u.ID == id);
Session["SiteSession"] = new SiteSession()
{
//Session data...
};
return PartialView("_IFrame");
}
This Action returns a Partial View that I ended up displaying in a jQuery UI modal dialog window.
Here's the code for that Partial View:
#{
ViewBag.SiteSession = (SiteSession)Session["SiteSession"];
}
<h2>Viewing Site As #ViewBag.SiteSession.DisplayName</h2>
<div>
<iframe src="#Url.Action("Index", "Home", new { Area = "" })"></iframe>
</div>
As you can see, it's extremely bare, and that's exactly what it needs to be. The <iframe> acts as a browser in a browser, allowing the Admin user full access to whichever Actions the selected User would.
For the sake of detail, here's the jQuery that creates the dialog and opens it:
$(function () {
$("#viewAsDialog").dialog({
modal: true,
autoOpen: false,
resizable: true,
draggable: true,
closeOnEscape: false,
height: $(window).height() * .9,
width: 1000,
closeText: '',
close: function () {
$.post("#Url.Action("End", "ViewAs", new { Area = "Admin" })")
.success(function (result) {
});
}
});
});
function viewAs(result) {
$("#viewAsDialog").html(result);
$("#viewAsDialog").dialog("open");
}
You can see here that the dialog is initialized on document-ready, and is not opened until the AJAX call that retrieves the Partial View is successfully completed.
Once the Admin closes the dialog, the server calls the End action in the ViewAs Controller, destroying the session:
[HttpPost]
public ActionResult End()
{
Session["SiteSession"] = null;
return new HttpStatusCodeResult(System.Net.HttpStatusCode.OK);
}

Joomla: jroute & navigating back up in menu hierarchy

I have a simple menu hierachy in a Joomla 1.5 site:
[Newsletters] -> [publisher A] -> [Newsletter A1]
-> [Newsletter A2]
-> [publisher B] -> [Newsletter B1]
-> [Newsletter B2]
When navigating this hierarchy using the menu items or breadcrumbs, the SEF URL's are as expected;
/newsletters/pubA.html
/newsletters/pubA/letterA1.html
/newsletters/pubA/letterA2.html
/newsletters/pubB.html
/newsletters/pubB/letterAB.html
/newsletters/pubB/letterAB.html
However, when navigating the hierarchy using links inside the pages, the url's get messed up. Read on for more details :)
The pages are generated by a component. I've implemented a JRouter to generate SEF URL's. With SEF turned on, I can correctly navigate the hierachy using menu items and the standard breadcrumbs.
However, I also want to navigate by links on the pages themselves (for example, by linking to all of a publisher's newsletters on the publisher's page, or by linking back to the publisher's page from a newsletter's page). This works fine when going from publisher to newsletter. The component calls
JRoute::_('index.php?option=' . $option . '&view=newsletter&newsletterid=' . $newsletterId );
and (correctly) generates a URL like:
/newsletters/pubA/letterA1.html
However, when a user is on a newsletter page and wants to go back up to the publisher's page, things go wrong. For some reason the publisher's alias gets added after the newsletter's alias in the URL, as if it was below the newsletter in the hierachy. The component calls
JRoute::_('index.php?option=' . $option . '&view=publisher&publisherid=' . $publisherId );
but that (incorrectly) generates a URL like:
/newsletters/pubA/letterA1/pubA.html
If I navigate forward to a newsletter again from the above URL, then the URL becomes
/newsletters/pubA/letterA1/letterA1.html
/newsletters/pubA/letterA1/pubA.html
/newsletters/pubA/letterA1/letterA1.html
/newsletters/pubA/letterA1/pubA.html
(i.e., it doesn't go deeper than one or two segment(s) 'wrong'.)
Also, please note that navigation does work (meaning, the right page is opened) -- it's just the URL that looks weird.
I don't see how I could generate the expected URL's as shown at the top; there doesn't seem to be a way to specify 'relative to what' the 'first' segment should be. Should I be tapping into JSite::getRouter() somehow?
The router code is pretty straight forward. It's the first time I write a router, so I could have messed up something. I do find it suspicious that ParseRoute is only ever called with a single segment.
function ComponentBuildRoute(&$query)
{
$segments = array();
if (isset($query['view']))
{
if (isset($query['newsletterid']))
{
$alias = { figure out newsletter alias from newsletter id }
$segments[] = $alias;
unset($query['newsletterid']);
}
else if (isset($query['publisherid']))
{
$alias = { figure out publisher alias from publisher id }
$segments[] = $alias;
unset($query['publisherid']);
}
unset($query['view']);
}
return $segments;
}
function ComponentParseRoute($segments)
{
$vars = array();
$id = { try to retrieve newsletter id matching alias in $segments[0] }
if (!empty($id))
{
$vars['view'] = 'newsletter';
$vars['newsletterid'] = $id;
return $vars;
}
$id = { try to retrieve publisher id matching alias in $segments[0] }
if (!empty($id))
{
$vars['view'] = 'publisher';
$vars['publisherid'] = $id;
return $vars;
}
return $vars;
}
I don't want to use an absolute URL because the publisher's menu item sits under the newsletters menu... obviously there must be a way of doing this as both the menu items and the breadcrumb modules figured it out...
Thanks
There is a problem with your ComponentBuildRoute. In the else if block where you deal with publisherid you unset newsletterid. I am not sure if that is the problem, but fixing it would be the first step to get this issue resolved.