So I am adding a page via the migration.cs file and this is working fine.
The issue comes that if I run the Update twice it will add the page twice.
While I know that in stage/prod this will not be the case.
But in dev we rerun the release code a few times to get it all working.
anyway what I want is something like
private readonly IContentManager _contentManager;
// this line is made up
var articleListingPage = _contentManager.GetPages.SingleOrDefault(p => p.Name == "ArticleListingPage");
if (articleListingPage == null)
{
var articlesPage = _contentManager.Create("Page");
articlesPage.As<TitlePart>().Title = "ArticleList";
articlesPage.As<BodyPart>().Text = #"<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus mauris magna, varius vel vulputate eget, bibendum id magna.</p>";
articlesPage.As<CommonPart>().Owner = _orchardServices.WorkContext == null ? null : _orchardServices.WorkContext.CurrentUser;
var articlesRoute = articlesPage.As<AutoroutePart>();
articlesRoute.DisplayAlias = _autorouteService.GenerateAlias(articlesRoute);
_autorouteService.PublishAlias(articlesRoute);
var menu = _menuService.GetMenu("Main Menu");
if (menu == null) throw new Exception("Could not get the menu. Please the name of the menu is correct.");
articlesPage.As<MenuPart>().Menu = menu;
articlesPage.As<MenuPart>().MenuText = "Article List YYYY";
articlesPage.As<MenuPart>().MenuPosition = "10";
_contentManager.Publish(articlesPage);
}
Does anyone know how to find a collections of pages/content?
I figured it out. As its dynamics its based on the Content Parts in the item.
In this example the "TitlePart" is added to the content type "Page"
var list = _contentManager.Query(VersionOptions.Published, "Page")
.List().Cast<dynamic>();
var existingPage = list.Any(i => i.TitlePart.Title == "ArticleList");
if (existingPage == false)
{
//add page etc
}
Related
I have a large amount of small textfiles where the first 4 or less lines contain metadata; following is an example
Lorem Ipsum
Tag1 Tag2 Tag3
Text
4204
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem Ipsum; would be the title
Tag1, Tag2, and Tag3; would be an array of tags
Text; would be the type
4204; would be the ID.
Lorem ipsum [...]; would be the actual content
I need to load the metadata without loading the actual content. Im working in node.js. I made following code:
function readMeta (path, callback) {
const meta = {};
const lineReader = require("readline").createInterface({input: require("fs").createReadStream(path)});
let lineCount = 0;
let interpretedMeta;
lineReader.on("line", line => {
interpretedMeta = interpretMeta(line, lineCount)
switch (lineCount) {
case 0:
meta.name = interpretedMeta;
break;
case 1:
meta.tags = interpretedMeta.split(" ");
break;
case 2:
meta.type = interpretedMeta;
break;
case 3:
meta.id = interpretedMeta;
}
++lineCount;
if (/^\s*$/.test(line)) {
lineReader.close();
}
});
lineReader.on("close", () => {
callback(meta);
process.exit(0);
});
}
where interpretMeta() is a function that formats the string given based on a linenumber. I will integrate this into readMeta() later since it's somewhat redundant.
Problem
This code works with one file, but bugs if it runs multiple times in a short amount of time. It reaches the second line but then starts over each time the function runs.
Im not 100% sure why this happens, but I assume something like lineReader.on()'s callback doesn't make copies of the variables it gets from readMeta happens. I can't figure out how to debug or solve though.
Fix
I have no experience whatsoever working with asynchronous functions, so apologies if i use the wrong terms onwards: I believe a way around my problem that i would be comfortable working with, is a synchronous readline() function that reads the next line in a stream. I can't figure out how to do this though, so my question is how do i:
A: fix the code
B: make a synchronous ´readline` function
Thanks
User O. Jones commented on the original post asking if this answer would answer my question. The aproved answer did not, but an answer below by User Lead Developer got me on the right track:
Update in 2019
An awesome example is already posted on official Nodejs documentation. here
This requires the latest Nodejs is installed on your machine. >11.4
const fs = require('fs');
const readline = require('readline');
async function processLineByLine() {
const fileStream = fs.createReadStream('input.txt');
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
// Note: we use the crlfDelay option to recognize all instances of CR LF
// ('\r\n') in input.txt as a single line break.
for await (const line of rl) {
// Each line in input.txt will be successively available here as `line`.
console.log(`Line from file: ${line}`);
}
}
processLineByLine();
The page he links to contains another example that i ended up following, following is my final code:
async function readMeta (path) {
const meta = {};
const lineReader = require("readline").createInterface({input: fs.createReadStream(path)});
let currentLine = 0;
lineReader.on("line", line => {
switch (currentLine) {
case 0:
meta.name = line;
break;
case 1:
meta.tags = line.split(" ");
break;
case 2:
meta.type = line;
break;
case 3:
meta.id = +line;
}
++currentLine;
if (/^\s*$/.test(line)) {
lineReader.close();
}
});
await once(lineReader, "close");
return meta;
}
Thanks for the help.
I have a logging command which works perfectly, the only issue is I can not finish the off section of the command. I need it to delete both records (guildid, channel) if the guildid matches.
This is what I have tried.
if (args[0] === 'off') {
message.channel.send('Logging turned off!');
const del = db.prepare('DELETE FROM logging WHERE guildid = ?;');
del.run({
guildid: `${message.guild.id}`
});
return;
Looking at the photo, when the args off is ran, I need it to delete the guildid contents (495602...) and channel contents (<#5290...) if the guildid contents matches with the guild the command was ran in.
Your current answer is the incorrect way to use prepared statement. If you use the way you pose, you open yourself up to SQL injection because you aren't interpreting the value you want to use in the statement as a value, you use it as part of the overall statement and then run the statement without parameters. That means that I could potentially provide a value that might not do exactly what you think it will.
For example the following won't do anything,
const $rowid = "3 OR rowid = 4";
const deleteStatement = db.prepare("DELETE FROM lorem WHERE rowid = $rowid");
deleteStatement.run({$rowid});
deleteStatement.finalize();
But this will delete elements with rowid 3 or 4:
const $rowid = "3 OR rowid = 4";
const deleteStatement = db.prepare(`DELETE FROM lorem WHERE rowid = ${$rowid}`);
deleteStatement.run();
deleteStatement.finalize();
Instead, take a look at the sqlite3 documentation here.
You need to actually paramaterize your prepared statement like the following:
const sqlite3 = require("sqlite3").verbose();
const db = new sqlite3.Database(":memory:");
db.serialize(function() {
// Make the table
db.run("CREATE TABLE lorem (info TEXT)");
// Create some dummy data
const insertStatement = db.prepare("INSERT INTO lorem VALUES (?)");
for (let i = 0; i < 5; i++) {
insertStatement.run(`My Data ${i}`);
}
insertStatement.finalize();
// Delete some data
const deleteStatement = db.prepare("DELETE FROM lorem WHERE rowid = $rowid");
deleteStatement.run({
$rowid: 3
});
deleteStatement.finalize();
// Print elements
db.each("SELECT rowid AS id, info FROM lorem", (err, {id, info}) => console.log(`${id}: ${info}`));
});
db.close();
For anyone in the future looking how to do this, this was the answer.
EDIT: Can't mark as an answer until 2 days lol
if (args[0] === 'off') {
message.channel.send('Logging turned off!');
db.prepare(`DELETE FROM logging WHERE guildid = '${message.guild.id}'`).run();
return;
Late to the better-sqlite3 party:
const del = db.prepare('DELETE FROM logging WHERE guildid = ?');
del.run(message.guild.id)
I'm trying to enable i18n to a little chrome extension that I'm working on.
As of now, I only need to translate some strings in the html file. I know that the i18n functionality cannot do that directly, so I wrote my own localization function:
var $objects = $('*[data-message]');
$objects.each(function() {
var $this = $(this);
var messageName = $this.attr('data-message');
var text = $this.html();
var translated = chrome.i18n.getMessage(messageName);
if (translated !== '' && translated !== undefined) {
$this.html(translated);
}
console.log(messageName); // this prints "theTitle"
console.log(translated); // this prints ""
});
This is a string that I have in my html file:
<span data-message="theTitle">Live Quotes Portfolio</span>
And this is my _locales/it/messages.json file:
{
"theTitle": {
"message": "Il titolo",
"description": "The string we search for.."
}
}
The problem is that in the two console logs, the first one prints the correct string that needs to be translated, but the second is always empty.
What am I missing? I also have "default_locale": "it" in my manifest.json...
I have a form in Laravel. I used pagination in this form and search option too. Pagination works fine when I didn't search anything. If I search something which has records more than 10 (my pagination record limit is 10), it shows result perfectly in first page but in second page or third page it shows the records of whole database. It's ignore the search criteria.
Controller Code:
public function index()
{
if (Input::has('invoiceNumber')) {
$invoiceNumber = Input::get('invoiceNumber');
$invoices = Invoice::where('invoiceNumber','like', '%'.$invoiceNumber.'%')->orderBy('date','desc')->paginate(10);
} elseif (Input::has('client')) {
$client = Input::get('client');
$invoices = Invoice::where('client','like', '%'.$client.'%')->orderBy('date', 'desc')->paginate(10);
} elseif (Input::has('startDate') && Input::has('endDate')) {
$startDate = Input::get('startDate');
$endDate = Input::get('endDate');
$invoices = Invoice::whereBetween('date', [$startDate, $endDate])->orderBy('date', 'desc')->paginate(10);
} elseif (Input::has('startDate')) {
$startDate = Input::get('startDate');
$invoices = Invoice::where('date', $startDate)->orderBy('date', 'desc')->paginate(10);
} elseif (Input::has('endDate')) {
$endDate = Input::get('endDate');
$invoices = Invoice::where('date', $endDate)->orderBy('date', 'desc')->paginate(10);
} else {
$invoices = DB::table('invoices')
->join('vehicles', 'invoices.vehicle', '=', 'vehicles.registration')
->select(
'invoices.*',
'vehicles.brand',
'vehicles.model',
'vehicles.seat',
'vehicles.remarks'
)
->orderBy('date', 'desc')
->paginate(10);
}
return view('invoice.index',compact('invoices'));
}
After performing search my URL look like this:
http://my-site.com/invoice?invoiceNumber=&client=&startDate=2016-01-01&endDate=2016-02-08
After this search when I click on page 2, the URL become this:
http://my-site.com/invoice?page=2
Try to use this bellow code (change as per your requirement)
return view('invoice.index')->withInvoices($invoices->appends(Input::except('page'));
Hope it's working for you...
In your view file, the render has to be like given below:
{!! $invoices->appends(Input::except('page'))->render() !!}
Simply use this on the result page.Pagination will be automatically visible at the bottom of the page
{!! $invoices->render() !!}
I need to validate inline editing in NetSuite.
I already have a Client Script in place that works great when editing the record normally.
I tried adding a User Event script that on the before save function that validates the record, but it appears this is ignored with inline editing.
Has anybody ran into this before?
Any insight you can provide would be helpful. Thanks!
Edits:
The relevant code from the UE script:
function beforeSubmit(type){
if (type == "create" || type == "edit" || type == "xedit") {
var status = nlapiGetContext().getSetting("SCRIPT", "...");
var amount = Number(nlapiGetContext().getSetting("SCRIPT", "..."));
var nr = nlapiGetNewRecord();
var entitystatus = nr.getFieldValue("entitystatus");
var projectedtotal = Number(nr.getFieldValue("projectedtotal"));
if (entitystatus == status && projectedtotal >= amount) {
var statusText = nr.getFieldText("entitystatus");
var message = "ERROR...";
throw nlapiCreateError("...", message, true);
}
}
}
This applies to the opportunity record.
The field being validated is Projected Total with id projectedtotal.
My mistake, I misunderstood how xedit handled nlapiGetNewRecord(). Calling nlapiGetNewRecord when in xedit only returns the edited fields, not the entire record. Thus, the if statement was never true in xedit mode, because either the amount or the status would be null (it was very unlikely the user would edit both at the same time, and validation relies on both these fields' values).
I edited the code to lookup the field value if it is not present in the new record. Now everything works as expected!
Thanks everyone for the help!
For reference, the corrected code is below.
function beforeSubmit(type){
if (type == "create" || type == "edit" || type == "xedit") {
var status = nlapiGetContext().getSetting("SCRIPT", "...");
var amount = Number(nlapiGetContext().getSetting("SCRIPT", "..."));
var nr = nlapiGetNewRecord();
//Attempt to get values normally
var entitystatus = nr.getFieldValue("entitystatus");
var projectedtotal = Number(nr.getFieldValue("projectedtotal"));
var id = nr.getId();
//If values were null, it's likely they were not edited and
//thus not present in nr. Look them up.
if(!entitystatus){
entitystatus = nlapiLookupField("opportunity", id, "entitystatus");
}
if(!projectedtotal){
projectedtotal = Number(nlapiLookupField("opportunity", id, "projectedtotal"));
}
if (entitystatus == status && projectedtotal >= amount) {
var message = "ERROR...";
throw nlapiCreateError("101", message, true);
}
}
}
In your user event are you checking the value of the type parameter. For inline editing, the value of the type is 'xedit'.