How to set the default directory for wysisyg editor insertImage in flask - flask

I'm building a CMS in flask and I have built a simple wysiwyg editor using execcommands for creating and editing posts, and everything is working. For the insertImage command I'm using an input element to open a directory and choose an image. It works except of course it opens my computers default folder. I want it to open the uploads folder in the static directory where user images are stored in flask. How?
I have searched through flask docs, Python handling files documentation and there's no mention of this. This is a project I'm doing for a class. I'm going above and beyond the requirements for this project but that's how I keep things interesting. I mean it's supposed to be a CMS right. Well, CMS's always have wysiwyg's that open the default "uploads" folder to insert media. Also, when creating my upload functions I found that when uploading files flask needs the absolute path. But when serving them the relative path is necessary.
Any point in the right direction would be greatly appreciated. Thank you.
Here's the structure
<div class="col-md-1 tools">
<a href="#" data-command='insertImage'data-toggle="tooltip" title="Insert Media"><i class='material-icons'>add_photo_alternate</i>
</a>
<div class="editorInputs">
<input type="file" name="media" id="insertImage"
accept="audio/*,video/*,image/*"/>
</div>
</div>
Here's my js script
$('.tools a').mousedown(function(e){
let command = $(this).data('command');
if(command == 'insertImage'){
$(this).next().children('input').trigger('click');
let input = $(this).next().children();
input.on('change', function(e){
let val = $(input).val();
document.execCommand(command, false, val);
})
}
});
Here's how my uploads file is configured in flask
app.config['SITE_UPLOADS'] = 'D:/Courses/Development/Programming/Python/LaunchCode/LC101/unit2/build-a-blog/static/site/uploads/'
app.config['ADMIN_UPLOADS'] = 'D:/Courses/Development/Programming/Python/LaunchCode/LC101/unit2/build-a-blog/static/admin/uploads/'
app.config['ALLOWED_IMAGE_EXTENSIONS'] = ['PNG', 'JPG', 'JPEG', 'SVG', 'GIF']
app.config['DATA_FILES'] = 'D:/Courses/Development/Programming/Python/LaunchCode/LC101/unit2/build-a-blog/data/'
app.config['RELATIVE_PATH_SITE'] = '../static/site/uploads/'
app.config['RELATIVE_PATH_ADMIN'] = '/static/admin/uploads/'

So, I realized that I have to create a function to pull images from the uploads folder, display them, get their URL and pass it to the execcommand. And I did.
First, create the gallery structure with radio buttons to view files. Then put the gallery in a bootstrap modal to fire when the execccomand insertImage link is clicked. Grab the URL of the checked image. pass it to the execcomand function in my js.
On the flask side get a list of all files in the uploads directory with os.listdir(absolute/path/to/directory), returns a python list of the files. Next create file urls and put info in a dict by looping over the filenames in the list and adding the relative path to the filename. Pass the dict to the jinja2 template and populate the gallery.
Finally, execute the js.
Here's my python code and js code.
def get_uploads():
list_images = os.listdir(app.config['ADMIN_UPLOADS'])
images = []
i =0
length = len(list_images)
while i < length:
img = {}
img['name'] = list_images[i]
img['url'] = os.path.join(app.config['RELATIVE_PATH_ADMIN'], list_images[i])
images.append(img)
i+=1
return images
Here's my js.
if(command == 'insertImage'){
$("#uploadsGallery").modal();
$('.ftco-animate').addClass('fadeInUp ftco-animated')
let check = $(this).next().find('input.form-check-input');
let val;
check.on('change', function(e){
val = $(this).val();
});
$('#insertImg').click(function (e) {
r.setStart(editDiv, lastCaretPos);
r.setEnd(editDiv, lastCaretPos);
s.removeAllRanges();
s.addRange(r);
document.execCommand(command, false, val);
check.prop('checked', false);
});
}

Related

Aspose.Word convert DOCX to HTML looses MERGEFIELD, IF conditions, headers and footer, table cell widths

I'm trying to write a online document editor with TinyMCE 5 as editor and Aspose.Word v20.8 as converter.
But when I convert the DOCX to HTML5 with Aspose.Word, it is not rendering as expected in TinyMCE.
The HTML looses for example headers, footers, MergeFields, IF, TableStart:TableEnd sofar I can tell now.
I need this HTML has all the data because I need to convert it back to DOCX again.
Code to generate the HTML5 is:
var doc = new Document({Stream_Of_DOCX});
var options = new HtmlSaveOptions();
options.SaveFormat = SaveFormat.Html;
options.Encoding = System.Text.Encoding.UTF8;
options.UpdateFields = true;
options.ExportRoundtripInformation = true;
options.ExportImagesAsBase64 = true;
options.ExportFontsAsBase64 = true;
options.ExportPageSetup = true;
options.ExportDocumentProperties = true;
options.ExportHeadersFootersMode = ExportHeadersFootersMode.PerSection;
options.HtmlVersion = HtmlVersion.Html5;
doc.Save($"{fileName}.html", options);
The code to convert the HTML5 back to DOCX is, were the model.Html is the TinyMCE textarea:
var doc = new Document();
var builder = new DocumentBuilder(doc);
builder.InsertHtml(model.Html);
doc.Save($"{fileName}.docx");
Can anybody help me to get this working with some code examples?
Or maybe has a better idear to accomplish the task.
The main idear is to be able to edit DOCX files online, without to have to download it and upload again with some windows service as client for example.
Aspose.Words do preserve headers and footers upon saving to HTML if ExportRoundtripInformation option is enabled. In this case Aspose.Words writes header and footer content with special css attributes, which are understood by Aspose.Words:
<div style="-aw-headerfooter-type:header-primary; clear:both">
<p style="margin-top:0pt; margin-bottom:0pt; line-height:normal">
<span>header</span>
</p>
</div>
Also, Aspose.Words preserves some fields (PAGE, NUMPAGES, NOTEREF, REF, AUTOR and TITLE). For example, PAGE field is exported like the following:
<span style="-aw-field-start:true"></span><span style="-aw-field-code:' PAGE \\* MERGEFORMAT '"></span><span style="-aw-field-separator:true"></span><span>1</span><span style="-aw-field-end:true"></span>
Such content is recognized by Aspose.Words upon reading HTML and loaded into the model as field. I logged a request WORDSNET-21037 to preserve other types of fields too.
I am not familiar with TinyMCE, but I suspect that custom attributes used by Aspose.Words for roundtrip MS Word features are removed and that is why Header and Footer are not preserved in your case.
Disclosure: I work at Aspose.Words team.

Show Image stored in s3 on Web page using flask

Im trying to get images from an s3 bucket, and show them on a web page using flask (and boto3 to access the bucket).
I currently have a list of all the pictures from the bucket, but cant get the html to show them(gives me 404 error).
How do I do this without downloading the files?
this is what I have so far:
def list_files(bucket):
contents = []
for image in bucket.objects.all():
contents.append(image.key)
return contents
def files():
list_of_files = list_files(bucket)
return render_template('index.html', my_bucket=bucket, list_of_files=list_of_files)
and this is the html snippet:
<table class="table table-striped">
<br>
<br>
<tr>
<th>My Photos</th>
{% for f in list_of_files %}
<td> <img src="{{ f }}"></td>
{% endfor %}
Thanks a lot!
since loading an image to a html page requires a real image which exists in the directory. images from AWS S3 can be loaded onto a html page if you download them first in the directory, then use its url as a source in html <image> tag.
i found a solution to this but you need to modify it as your needs.
define a function that loads the image from S3 as:
import matplotlib.image as mpimg
import numpy as np
import boto3
import tempfile
s3 = boto3.resource('s3', region_name='us-east-2')
bucket = s3.Bucket('bucketName')
object = bucket.Object('dir/subdir/2015/12/7/img01.jpg')
tmp = tempfile.NamedTemporaryFile()
def imageSource(bucket, object, tmp):
with open(tmp.name, 'wb') as f:
object.download_fileobj(f)
src = tmp.name #dir/subdir/2015/12/7/img01.jpg
retrun src
Just ran into this problem as well, seems like this hasn't been updated for a while so will try to add it.
Your current approach below is right. The only issue is that in order to render an image that is not going to be downloaded to your server, you have to have a direct url to your S3 file. Currently, you only have the image name, not the full url.
def list_files(bucket):
contents = []
for image in bucket.objects.all():
contents.append(image.key)
return contents
def files():
list_of_files = list_files(bucket)
return render_template('index.html', my_bucket=bucket, list_of_files=list_of_files)
Currently, your items in the list of files will look like this:
['file_name1', 'file_name2', 'file_name3']
In order for them to render in your browser directly you need them to look like this:
['file_url1', 'file_url2', 'file_url3']
s3 file urls look something like this: https://S3BUCKETNAME.s3.amazonaws.com/file_name1.jpg
Therefore, instead of the line below
contents.append(image.key)
you need to replace the image.key with something that makes the URL
contents.append(f'https://{S3BUCKETNAME}.s3.amazonaws.com/{image.key})
That should do it, the html you have should work correctly as is. The only other big risk is the files you uploaded are not public, for that you'll need to look at the settings of your bucket on AWS.
Additional Resources and Sources:
Adding a public policy to your AWS S3 Bucket: https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies.html
Uploading and downloading files with Flask & S3: https://stackabuse.com/file-management-with-aws-s3-python-and-flask/

How to download file from local directory using python

I want to download a file from the local directory when the user clicks on a particular link. How I can do it using python.
Try this on click of link:
location.replace('your_loacal_filepath')
For Example:
location.replace('/files/out.txt')
if you are rendering HTML, then you should read about the HTML download Attribute
Quoting
The download attribute specifies that the target will be downloaded when a user clicks on the hyperlink.
This attribute is only used if the href attribute is set.
else if(currentobj.filename != null){
var xy = '{% static "/documents/dataset/" %}' + currentobj.filename;
alert(xy);
var $tr = $('<tr><td style="padding:5px;"><a href="'+ xy +'"
target="_blank" download>' + currentobj.filename.slice(0,25) +
"....." +'</a></td> </tr>');
$tbl.append($tr);
}
just add download tag along the hyperlink
if you want to specify a specific name for the download file then just mention it like this
<a href="/images/myw3schoolsimage.jpg" download="w3logo">
You can try this.
The download attribute instructs browsers to download a URL instead of navigating to it.
Check out. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#Attributes

Scalatra link image file outside application

I can't seem to figure out how to display a file in a view that is located outside of the .war file. In the application I am working on I have a folder of images that is volatile at '/path/to/images/'. I am trying to link the file 'myfile.jpg' inside an img tag. In my view (scaml) I have the following code:
-val path = "/path/to/images/" + filename
%img(src = path)
This renders the following img tag
<img src="/path/to/images/myfile.jpg"/>
Scalatra resolves the src url to this invalid url
http://localhost/path/to/images/myfile.jpg
I'm kind of stuck. Can anyone point me in the right direction? I cannot store these images within /src/main/webapp/img
Many thanks,
AH

Sugarcrm : How to rewrite a document URL

My version :
SugarCRM CE 6.5.2 running on linux
What I want to do :
I've customized the Documents module in "custom/modules/Documents" by writing several logic hooks.
These logic hooks creates new folders in "ressources/" which is my new upload folder. (I've change the 'upload_dir' from "./upload" into "./ressources" in the config.php)
This is done through a custom field created in studio named "folder_name"
And then, the logic hooks cut and paste the document uploaded into this new folder.
What is my problem
So, with all of this, my download url in Edit, Detail and Revisions Subpanel Views is false. I would like to change it to the right folder, like, for example adding a folder parameter in the url
like this :
/index.php?entryPoint=download&folder=Images&id=idDoc&type=Documents
I tried to change the a href link in EditView.tpl or DetailView.tpl, (like )
but it didn't work since they were located in my cache/modules/Documents folder and were overriding when i did a quick repair.
So I copies/pasted the DetailView.tpl and the EditView.tpl into custom/modules/Documents/tpls and tried to override the view.edit.php and the view.detail.php to link the customized templates, but it did not work.
code :
<?php
require_once('include/MVC/View/views/view.detail.php');
class DocumentsViewDetail extends ViewDetail {
function DocumentsViewDetail() {
parent::ViewDetail();
}
function display() {
parent::display();
}
function detailViewProcess() {
$this->processSearchForm();
$this->lv->searchColumns = $this->searchForm->searchColumns;
if (!$this->headers)
return;
if (empty($_REQUEST['search_form_only']) || $_REQUEST['search_form_only'] == false) {
//here we are overriding with your custom template
$this->lv->setup($this->seed, 'custom/modules/Documents/tpls/DetailView.tpl', $this->where, $this->params);
echo $this->lv->display();
}
}
}
?>
Do you have any idea why this doesn't work?
Do you have any idea on how i could rewrite my URLS or override the Edit, Revisions SubPanel and Details Views?
Please answer, this is URGENT
Thank you by advance.
Try adding the folder parameter to the variable $file_url inside the method fill_in_additional_detail_fields() in modules/Documents/Document.php.
[Edited]
EditView: include/SugarFields/Fields/File/EditView.tpl
DetailView: include/SugarFields/Fields/File/DetailView.tpl
<a href="index.php?entryPoint=download&id={$fields.{{$vardef.fileId}}.value}&type={{$vardef.linkModule}}&folder=test" ...
ListView: include/SugarFields/Fields/File/ListView.tpl
<a href="index.php?entryPoint=download&id={$parentFieldArray.ID}&type={$displayParams.module}{$vardef.displayParams.module}&folder=test" ...
So, thanks to #air4x, i did answer my trouble : overriding the DetailView.tpl
To make it upgrade-safe, i copies it from
include/SugarFields/Fields/File/DetailView.tpl
to
custom/include/SugarFields/Fields/File/DetailView.tpl
It works!
BUT there is a big trouble coming...
explanations :
1] I create a new Document, uploading image01 to Folder01. Save. Database ok. in DetailView the folder name is "Folder01" and the link '//Folder01/image01_id' works.
2] I create another new Document, uploading image02 to Folder02. Save. Databse ok. BUT in DetailView the folder's name is not "Folder02" but "Folder01". AND the link is //Folder01/image02_id so it doesn't work, because in database or in my folders, the file is still in Folder02.
Here is my custom/include/SugarFields/Fields/File/DetailView.tpl code :
//BEGIN the code i modified
<span class="sugar_field" id="{{if empty($displayParams.idName)}}{{sugarvar key='name'}}{{else}}{{$displayParams.idName}}{{/if}}">
<a href="ressources/{$fields.folder_name_c.value}/{$fields.{{$vardef.fileId}}.value}" class="tabDetailViewDFLink" target='_blank'>{{sugarvar key='value'}}</a>
</span>
//END the code i modified
{{if isset($vardef) && isset($vardef.allowEapm) && $vardef.allowEapm}}
{if isset($fields.{{$vardef.docType}}) && !empty($fields.{{$vardef.docType}}.value) && $fields.{{$vardef.docType}}.value != 'SugarCRM' && !empty($fields.{{$vardef.docUrl}}.value) }
{capture name=imageNameCapture assign=imageName}
{$fields.{{$vardef.docType}}.value}_image_inline.png
{/capture}
{sugar_getimage name=$imageName alt=$imageName other_attributes='border="0" '}
{/if}
{{/if}}
{{if !empty($displayParams.enableConnectors)}}
{{sugarvar_connector view='DetailView'}}
{{/if}}
I really don't know why my $fields.folder_name_c.value stay from the first document and replace the one in the second document...
Do you know how i could do a sql query in my EditView.tpl to change it and have the right value?
Please, i really need help.
Thank you
(ps : #air4x, thanks a LOT, even if i have another trouble, that showed me hox to override EditView. THANK YOU! )