Odoo v8 uses Qweb and we need to print the terms and conditions of sale on the last page of the invoice.
As I understand we need to test that it is the last page of the report and print some static HTML on this page.
Does anyone know how to test the last page and remove the header and footer from it to achieve what I am trying.
Or even another way of doing it.
In last version of odoo, version 8 (or saas-6), to enable special class names to do special things (as for instance a 'last-page' class name to trigger visibility), you should only modify report module, in static/src/js/subst.js, and add this code to the subst function:
var operations = {
'last-page': function (elt) { elt.style.visibility = (vars.page === vars.topage) ? "visible" : "hidden"; },
};
for (var klass in operations) {
var y = document.getElementsByClassName(klass);
for (var j=0; j<y.length; ++j) operations[klass](y[j]);
}
In the QWEB ir.ui.views used by your report, you can then add anywhere (header, body, footer), code with:
<div class="last-page">
My content only displayed if on last page.
<div>
EDIT: An OpenERP/Odoo addon to add this magic class last-page easily was implemented as an example: https://github.com/0k/report_extended
Related
I have two editors on the screen, one read-only. What I want to do is allow the user to select content from the read-only editor and paste it into the current position of the other by clicking a button. (the logic may manipulate the text which is one reason I don't want to use the system's clipboard.)
So far I have the function that is able to paste the text like as follows. (I am using the Angular wrapper which explains the presence of the CKEditorComponent reference.
doPaste(pasteEvent: PasteEvent, editorComponent: CKEditorComponent) {
const editor = editorComponent.editorInstance;
editor.model.change(writer => {
writer.insertText(pasteEvent.text, editor.model.document.selection.getFirstPosition() );
});
}
What I can't find from the documentation is how to extract the selected text. What I have so far is:
clickPasteSelectedPlain(editorComponent: CKEditorComponent) {
const editor = editorComponent.editorInstance;
const selection = editor.model.document.selection;
console.log('clickPasteAll selection', selection);
console.log('clickPasteAll selectedcontent', editor.model.document.getSelectedContent);
}
The selection appears to change depending on what is selected in the editor's view. The getSelectedContent function is undefined. How do I get the content?
With a bit of poking around I figured out how to do this. I'll document it here on the chance that it will help someone down the road avoid the process of discovery that I went through.
On the source document I have a ckeditor element like this:
<div *ngIf="document">
<ckeditor #ckEditor
[editor]="Editor" [config]="ckconfig" [disabled]="true"
[(ngModel)]="document.text"></ckeditor>
<button mat-flat-button (click)="clickPasteSelectedPlain(ckEditor)">Paste Selected Text Plain</button>
</div>
In the component the function called on the click event is like this:
#Output() paste = new EventEmitter<PasteEvent>();
...
clickPasteSelectedPlain(editorComponent: CKEditorComponent) {
const editor = editorComponent.editorInstance;
this.paste.emit({
content: editor.model.getSelectedContent(editor.model.document.selection),
obj: this.document,
quote: false
});
}
The PasteEvent is defined as an exported interface which I will omit here to save space. The content key will refer to a DocumentFragment.
Note that I am passing the CKEditorComponent as a parameter. You could also access it via an Angular #ViewChild declaration but note that my ckeditor is inside an *ngIf structure. I think that works well in Angular 6 but in the past I have had difficulty with #ViewChild references when the target was conditionally in the DOM. This method always works but use whatever method you want.
The event fired by the emit is processed with a method that looks like this:
doPaste(pasteEvent: PasteEvent, editorComponent: CKEditorComponent) {
const editor = editorComponent.editorInstance;
editor.model.insertContent(pasteEvent.content);
}
Because the content is a DocumentFragment the paste operation will include all formatting and text attributes contained in the selected source. But that's all there is to it.
I'm currently writing a site using Sitefinity CMS. Can someone please explain how to get the current dynamic content item from server side code on page_load?
I have written a user control to display a custom gallery of sliding images. There are multiple content types in my dynamic module. The user control will sit as part of the masterpage template rather than on every page. On each page load I would like to fetch the current dynamiccontent item that is associated with the page and examine whether it has a property with the name 'Gallery'. If so I would then extract the images and render them via the usercontrol.
Thanks,
Brian.
I'm assuming your images are related content. This gets every published content item of your type.
var dynamicModuleManager = DynamicModuleManager.GetManager();
var moduleType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.YOURTYPEHERE");
var dcItems = dynamicModuleManager.GetDataItems(moduleType)
.Where(l => l.Status == ContentLifecycleStatus.Master);
foreach (var dcItem in dcItems)
{
//pass the dynamic content item to a model constructor or populate here, then
// get your image this way:
var image = dcItem.GetRelatedItems<Image>("Images").SingleOrDefault();
if (image != null)
{
ImageUrl = image.MediaUrl;
}
}
I am creating a custom module in Orchard CMS 1.7.1
So far all is going well (ish)
One of my properties is a string (called InfoBubbleHtml).
I would like to utilise the rich text edit for this input on my modules create/edit form.
Is there a helper already in place that would render my property as a rich text area rather than just a textarea or input field?
If not, what would i need to do to be able to have this property render the rich text editor?
Thanks in advance.
Update
As an update/addition to this question... Any HTML that I enter into my current text area is being ignored; guessing to do with request validation. how is this disabled for my controller so i can allow html in the admin?
Update 2
Ok, so i have figured out how to add this to my view by using:
#Display.Body_Editor(Text:Model.InfoBubbleHtml,EditorFlavor:"html")
Any idea how to set the ID of the editor?
#Display.Body_Editor(Text:Model.InfoBubbleHtml,EditorFlavor:"html") is rendering a shape named Body.Editor.cshtml.
This file lives in : Orchard.Web\Core\Common\Views\Body.Editor.cshtml
And it's content is
#using Orchard.Utility.Extensions;
#{
string editorFlavor = Model.EditorFlavor;
}
#Html.TextArea("Text", (string)Model.Text, 25, 80, new { #class = editorFlavor.HtmlClassify() })
So using this Shape you cannot set Id, Model is the anon that you send on the Display (Text and EditorFlavor).
Shapes.cs on Orchard.Core/Common is hooking an alternate using the EditoFlavor string.
public void Discover(ShapeTableBuilder builder) {
builder.Describe("Body_Editor")
.OnDisplaying(displaying => {
string flavor = displaying.Shape.EditorFlavor;
displaying.ShapeMetadata.Alternates.Add("Body_Editor__" + flavor);
});
}
So the final file that is rendered : TinyMVC\Views\Body-Html.Editor.cshtml
using Orchard.Environment.Descriptor.Models
#{
var shellDescriptor = WorkContext.Resolve<ShellDescriptor>();
}
<script type="text/javascript">
var mediaPickerEnabled = #(shellDescriptor.Features.Any(x => x.Name == "Orchard.MediaPicker") ? "true" : "false");
var mediaLibraryEnabled = #(shellDescriptor.Features.Any(x => x.Name == "Orchard.MediaLibrary") ? "true" : "false");
</script>
#{
Script.Require("OrchardTinyMce");
Script.Require("jQueryColorBox");
Style.Require("jQueryColorBox");
}
#Html.TextArea("Text", (string)Model.Text, 25, 80,
new Dictionary<string,object> {
{"class", "html tinymce"},
{"data-mediapicker-uploadpath",Model.AddMediaPath},
{"data-mediapicker-title",T("Insert/Update Media")},
{"style", "width:100%"}
})
You need to add this to the template and include another parameter in the TextArea Dictionary parameter named : {"id", "THE ID YOU LIKE"}.
Take a look at the docs about Shapes if you want to learn more Docs
You can patch the TinyMVC\Views\Body-Html.Editor.cshtml file to enable it to use custom Name/ID for the text area. The modification is quite simple - replace
#Html.TextArea("Text", (string)Model.Text, 25, 80,
with
#Html.TextArea((string)Model.PropertyName ?? "Text", (string)Model.Text, 25, 80,
Now you can use additional parameter PropertyName in your call:
#Display.Body_Editor(PropertyName:"InfoBubbleHtml", Text:Model.InfoBubbleHtml, EditorFlavor:"html")
The downside is that you are patching a foreign code and have to reapply this patch every time this file in TinyMVC module is updated.
I am using dompdf to generate reports which sometimes has a front page, and sometimes has some attachments. The main content has a header and a footer, but the front page and the attachments (the last 3 to 5 pages of the pdf) should not contain header and footer. I'm placing the header and footer with a inline php page_script(), like this:
<script type="text/php">
if (isset($pdf) ) {
$pdf->page_script('
if ( $PAGE_COUNT > 10 && $PAGE_NUM == 1) {
//front page footer
}else{
//other pages' header and footer
}
');
}
</script>
The whole report is built by a database engine which outputs it all as a temporary html.txt-file which is then read into DOMPDF.
Now, to recognize the front page I just have to check if the page number is = 1. If any attachments are added (which are comprised of 1000px-height jpg images, each on their own page)
Does anyone have an idea for how to identify these "attachment"-pages and get DOMPDF to not render a header and footer on those pages? Or is there any way I could check within the page_script()-script whether the current page contains only an image (or perhaps an image with a specific class or identifier)?
Thanks for any help,
David
Detecting the current page contents may be possible, but I'd have to research exactly what you can do at this level. An easier method would be if you could inject some inline script in your generated document. After the main content and before the attachments you could add something like $GLOBALS['attachments'] = true; and then add a check on the status of this variable to your conditional.
<script type="text/php">
if (isset($pdf) ) {
$pdf->page_script('
if ( $PAGE_COUNT > 10 && $PAGE_NUM == 1) {
//front page footer
}elseif ($GLOBALS['attachments']) {
//attachments actions
}else{
//other pages' header and footer
}
');
}
</script>
Of course, don't forget to initialize the variable to false at the top of the document.
(from https://groups.google.com/d/topic/dompdf/mDsYi8Efnhc/discussion)
I'm generating a PDF with iText, in that I'm displaying a header and footer.
Now i want to remove header for a particular page.
For eg: If I'm generating a 50 pages pdf, for the final 50th I don't want to show header,
how could this be achieved?
Here's my code where I'm generating footer (header part removed).
public class HeaderAndFooter extends PdfPageEventHelper {
public void onEndPage (PdfWriter writer, Document document) {
Rectangle rect = writer.getBoxSize("art");
switch(writer.getPageNumber() % 2) {
case 0:
case 1:
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_CENTER, new Phrase(String.format("%d", writer.getPageNumber())),
300f, 62f, 0);
break;
}
}
}
Any suggestions? Thanks in advance.
You can use a 2-pass approach:
1st pass : generate the PDF file without header
2nd pass : stamp the header on all but the last page
Have a look at this example taken from the iText book. You'll just have to adapt the second pass by only going through the N-1 first pages:
int n = reader.getNumberOfPages() - 1;
instead of
int n = reader.getNumberOfPages();
I was also in need to do the same. I want to share how I resolved this issue.
The Idea is, for the automatic generation of header footer, we set page event on PDFWriter like:
HeaderAndFooter event= new HeaderAndFooter(); //HeaderAndFooter is the implementation of PdfPageEventHelper class
writer.setPageEvent(event);// writer is the instance of PDFWriter
So, before the content of the last page, We can remove the event:
event=null;
writer.setPageEvent(event);
It works for me without any error or exception.