How to create standalone custome page? - keystonejs

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.

Related

Autodesk PDF Extension - Preventing page in query string override

I'm currently looking to implement pagination within the ForgeViewer PDF Extenstion, in the documentation there's a note that 'page' in the querystring will override any value passed to load model. I wondered if this was configurable or we were able to prevent this.
// URL parameter page will override value passed to loadModel
viewer.loadModel(‘path/to/file.pdf’, { page: 1 });
This is causing us a few issues as we use 'page' for other purposes and we'll have to rework quite a bit to rename our current page querystring which we're using for paginating tables.
That's correct. If you look inside the PDF extension's code (https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/extensions/PDF/PDF.js) then you'll find that this behaviour is hardcoded unfortunately 😞
I can think of two workarounds:
a) Use a URL param other than page - e.g. sheet?
b) Overwrite the current URL so that the page number will become what you need
// Original URL is: http://127.0.0.1:5500/index.html?page=2
// we change it to page=1
// This should change the URL content without a reload
history.pushState('', '', 'index.html?page=1');
viewer.loadModel("AutoCAD_Sample_Part1.pdf", {}, (model) => {
You could also achieve the same like this:
viewer.loadExtension('Autodesk.PDF').then(function(ext) {
// Original URL is: http://127.0.0.1:5500/index.html?page=2
// we change it to page=1
viewer.loadModel("AutoCAD_Sample_Part1.pdf", {}, (model) => {
ext.hyperlinkTracker.changePage(1)

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
})

Should Durandal url hashes include the id?

Using the HTML Starter Kit example for Durandal 2.0.1.
If I add a route for customers/:id with my own vm and view I can navigate to the page c://temp/index.html#customer/123 and the page displays and in activate I can see the parameter of 123. However, the hash for that page shows as customer/:id Should the router automatically update these hashes to include any passed parameters or is this something I have to do myself?
There may be a baked in fix for this but if you are going to be using the hash and you have the Id or optional Id stuff in there you can use this helper for navigation and to clean up the hash, if needed -
function changeRoute(route) {
var cleanRoute = route.hash;
if (cleanRoute.indexOf(':id') !== -1) {
cleanRoute = cleanRoute.replace(':id', '');
}
return router.navigate('#' + thisRoute);
}
Or you could just as easily add an additional setting on the route to use as the cleaned hash.

blueimp file upload. How to clean existing filelist

I have goggled a lot, but have not found a solution for my issue. The author of the widget references to the last answer of FAQ, but the FAQ does not have the answer or I cannot find it. I suppose it was updated since that time. Other fellows who faced the same issue and asked the same question just gone and did not provide any solution.
Anyway, in my case I have a table with button Pictures:
When a user clicks one of pictures button, modal dialog is shown. The user now can manage pictures for the chosen row. He can upload, delete pictures and so on. When the user opens the dialog for second row in the table he should see pictures for the second row only. It tells me that I have to clean the list of uploaded files every time user hits Pictures button to see the dialog. He will receive list of pictures which corresponds to chosen row from the server. Unfortunately, when I retrieve the list for the chosen row, the received files are added to the existing list.
Could you tell me how I can clean the list or reset the widget without removing files on the server side?
UPDATE I have used the following piece of code as a temporary solution.
jQuery.ajax({
url: "<YOUR URL HERE>",
dataType: 'json',
context: $('#fileupload')[0]
}).done(function (result) {
jQuery("#fileupload").find(".files").empty(); //this line solves the issue
jQuery(this).fileupload('option', 'done').call(this, null, { result: result });
});
Thank you.
i was also trying for one hour to get my upload work ;)
here is, how i solved this problem:
$('#html5FileInput').fileupload({
....
add: function (e, data) {
$.each(data.files, function (index, file) {
var newFileDiv = $(newfileDiv(file.name));
$('#fsUploadProgressHtml5').append(newFileDiv);
newFileDiv.find('a').bind('click', function (event) {
event.preventDefault();
var uploadFilesBox = $("#fsUploadProgressHtml5");
var remDiv = $(document.getElementById("fileDiv_" + event.data.filename));
removeFileFromArray(event.data.filename);
remDiv.remove();
data.files.length = 0;
...
});
data.context = newFileDiv;
});
...
)};
as you can see i create inside the add-event my file-dataset with 'newfileDiv(file.name)'. this creates a div with all information about the file (name, size, ...) and an ankor that exists for deleting the file from the list. on this ankor i bind a click-event in which i have the delete implementation.
hope this helps!
I know this isn't the most elegant solution, but I needed a very quick and dirty...so here's what I did (using jQuery).
//manually trigger the cancel button for all files...removes anything that isn't uploaded yet
$('.fileupload-buttonbar .cancel').first().trigger('click');
//check the checkbox that selects all files
if(!$('.fileupload-buttonbar .toggle').first().checked) {
$('.fileupload-buttonbar .toggle').first().trigger('click');
}
//manually trigger the delete button for all files
$('.fileupload-buttonbar .delete').first().trigger('click');
I know this isn't the best way. I know it isn't elegant...but it works for me and removes everything from the plugin.
If you have added file names or anything else from the plugin to any local arrays or objects, you'll need to clean those up manually (I have several handlers that fire on fileuploadadded, fileuploadsent, fileuploadcomplete, fileuploadfailed, and 'fileuploaddestroyed` events).
protected function get_file_objects($iteration_method = 'get_file_object') {
$upload_dir = $this->get_upload_path();
if (!is_dir($upload_dir)) {
return array();
}
return array_values(array_filter(array_map(
array($this, $iteration_method)
//scandir($upload_dir)
//File listing closed by Doss
)));
}
there is a scandir function responsible for listing the files. just uncomment it like i have done above and your problem is solved. it can be found in the UploadHandler.php file.

How do I get data from a background page to the content script in google chrome extensions

I've been trying to send data from my background page to a content script in my chrome extension. i can't seem to get it to work. I've read a few posts online but they're not really clear and seem quite high level. I've got managed to get the oauth working using the Oauth contacts example on the Chrome samples. The authentication works, i can get the data and display it in an html page by opening a new tab.
I want to send this data to a content script.
i'm having a lot of trouble with this and would really appreciate if someone could outline the explicit steps you need to follow to send data from a bg page to a content script or even better some code. Any takers?
the code for my background page is below (i've excluded the oauth paramaeters and other )
` function onContacts(text, xhr) {
contacts = [];
var data = JSON.parse(text);
var realdata = data.contacts;
for (var i = 0, person; person = realdata.person[i]; i++) {
var contact = {
'name' : person['name'],
'emails' : person['email']
};
contacts.push(contact); //this array "contacts" is read by the
contacts.html page when opened in a new tab
}
chrome.tabs.create({ 'url' : 'contacts.html'}); sending data to new tab
//chrome.tabs.executeScript(null,{file: "contentscript.js"});
may be this may work?
};
function getContacts() {
oauth.authorize(function() {
console.log("on authorize");
setIcon();
var url = "http://mydataurl/";
oauth.sendSignedRequest(url, onContacts);
});
};
chrome.browserAction.onClicked.addListener(getContacts);`
As i'm not quite sure how to get the data into the content script i wont bother posting the multiple versions of my failed content scripts. if I could just get a sample on how to request the "contacts" array from my content script, and how to send the data from the bg page, that would be great!
You have two options getting the data into the content script:
Using Tab API:
http://code.google.com/chrome/extensions/tabs.html#method-executeScript
Using Messaging:
http://code.google.com/chrome/extensions/messaging.html
Using Tab API
I usually use this approach when my extension will just be used once in a while, for example, setting the image as my desktop wallpaper. People don't set a wallpaper every second, or every minute. They usually do it once a week or even day. So I just inject a content script to that page. It is pretty easy to do so, you can either do it by file or code as explained in the documentation:
chrome.tabs.executeScript(tab.id, {file: 'inject_this.js'}, function() {
console.log('Successfully injected script into the page');
});
Using Messaging
If you are constantly need information from your websites, it would be better to use messaging. There are two types of messaging, Long-lived and Single-requests. Your content script (that you define in the manifest) can listen for extension requests:
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.method == 'ping')
sendResponse({ data: 'pong' });
else
sendResponse({});
});
And your background page could send a message to that content script through messaging. As shown below, it will get the currently selected tab and send a request to that page.
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {method: 'ping'}, function(response) {
console.log(response.data);
});
});
Depends on your extension which method to use. I have used both. For an extension that will be used like every second, every time, I use Messaging (Long-Lived). For an extension that will not be used every time, then you don't need the content script in every single page, you can just use the Tab API executeScript because it will just inject a content script whenever you need to.
Hope that helps! Do a search on Stackoverflow, there are many answers to content scripts and background pages.
To follow on Mohamed's point.
If you want to pass data from the background script to the content script at initialisation, you can generate another simple script that contains only JSON and execute it beforehand.
Is that what you are looking for?
Otherwise, you will need to use the message passing interface
In the background page:
// Subscribe to onVisited event, so that injectSite() is called once at every pageload.
chrome.history.onVisited.addListener(injectSite);
function injectSite(data) {
// get custom configuration for this URL in the background page.
var site_conf = getSiteConfiguration(data.url);
if (site_conf)
{
chrome.tabs.executeScript({ code: 'PARAMS = ' + JSON.stringify(site_conf) + ';' });
chrome.tabs.executeScript({ file: 'site_injection.js' });
}
}
In the content script page (site_injection.js)
// read config directly from background
console.log(PARAM.whatever);
I thought I'd update this answer for current and future readers.
According to the Chrome API, chrome.extension.onRequest is "[d]eprecated since Chrome 33. Please use runtime.onMessage."
See this tutorial from the Chrome API for code examples on the messaging API.
Also, there are similar (newer) SO posts, such as this one, which are more relevant for the time being.