Adding full path to django MarkdownX images? - django

I have added a MarkdownxField to my django model, and it works well. I can edit it witha proper preview from the admin panel.
However, when I added images to the markdown there's a problem. My app is built in React and is served from a different port on the domain. When MarkdownX adds the image to the markdown file it does so with a relative path, so the call goes to the client port instead of the server port where it automatically saves the image.
I've looked through the settings options for MarkdownX but couldn't find something that would help out. The image is uploaded an saved well. But the client side can't get to it.

So this isn't exactly what I was going for in the question, but I solved it in the Client side in this by injecting the full path when parsing the markdownx content.
Just in case anyone gets stuck on it here's what i did:
// This util function acts as a middleware when i collect the data.
import { serverPath } from "../serverPaths";
const markdownImageInjector = (data: string): string => {
let injected = data.replace(
/!\[\]\(\/media\/markdownx\//g,
`![](${serverPath}media/markdownx/`
);
return injected;
};
export default markdownImageInjector;
and here is the action:
const getArticle = (id: string) =>
axios
.get(`${apiPath}/articles/${id}`)
.then(res => {
let data = res.data;
data.content = markdownImageInjector(data.content);
return data;
})

The possible solution (maybe the hard one too) is, provide the absolute path to the image
Ex:
![MyImage](https://my.domain.com/mediafiles/markdownx/e4692afa-9608-4fac-bd85-c28209879d0b.png)

Related

How to recreate/reload app when external config/database changes in Flask

I’m making a server to convert Rmarkdown to Dash apps. The idea is parse all params in the rmd file and make corresponding Dash inputs. Then add a submit button which compile the rmd to html somewhere and iframe back. I use an external database to store the info for rmd paths so user can dynamically add files. The problem is when a rmd file changes, the server has to reparse the file and recreate the app and serve at the same url. I don’t have an elegant solution. Right now I’m doing something like this.
server = Flask(__name__)
#server.route(“rmd/path:path”):
def convert_rmd_to_dash(path):
file = get_file_path_from_db(path)
mtime = get_last_modified_time(file)
cached_app, cached_mtime = get_cache(path)
if cached_mtime == mtime:
return cached_app
inputs = parse_file(file)
app = construct_dash_app(inputs)
return app.index()
def construct_dash_app(inputs):
app = dash.Dash(
name,
server=server,
routes_pathname_prefix=’/some_url_user_will_never_use/’ + file_name + time.time())
app.layout = …
…
return app
It works but I get many routing rules under /some_url_user_will_never_use. Directly overwriting rmd/path might be possible but feels hacky based on Stackoveflow’s answer. Is there a better solution? Thanks.

Form redirects to page /form_action_cc611e1d

I installed the contact_storage module so I can set a redirect path when completing a form, whenever I complete a form it apparently ignores whatever I have filled into the redirect path field and sends me to "/form_action_cc611e1d".
I have no idea where this comes from, the only reference I find to this path in my code is in the BigPipe core module, except this module has not been active in my project.
I've cleared cache a 100 times but to no avail. Does anyone have any idea how to resolve this?
It seems the redirect only happens when attaching a js library in the hook_form_FORM_ID_alter() of my form, this js adds some html (no form controls just some div's) and some click handlers.
This only happens in 1 of our 6 templates though so there must be something else interfering, unfortunately I ran out of time to further investigate this.
To fix the form I simply added the request uri to the form again:
function schade_forms_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id){
//attach JS
$form['#attached'] = array(
'library' => array(
'insusite_forms/form',
),
);
//to prevent the form from redirecting to /form_action_cc611e1d after submit add the action link
$form['#action'] = \Drupal::request()->getRequestUri();
}
}

cloudinary direct upload form is not valid, need to re upload

i am using django and cloudinary direct upload to upload iamges
it is working if the form is valid.
but if my form is not valid, my page reloaded, and then the form will ask the user to upload the image again.
any way to solve this?
my code is attached below.
since i use direct upload, after an image is uploaded. it will be displayed immediately on the front end.
but when the form is invalid and the form is refreshed, the image is gone. ( after your latest update, it is true i do not need to re upload the photo again. but the photo is gone. how to display that again?)
thanks.
<script>
$('.cloudinary-fileupload').bind('cloudinarydone', function(e, data) {
var imag_var = $.cloudinary.image(data.result.public_id, {
format : data.result.format,
version : data.result.version,
transformation : 'form_preview'
});
$('.preview').html(imag_var);
$('.status_value').text('Uploaded:' + data.result.public_id);
$('#id_cover_image').val(data.result.public_id);
return true;
});
$('.cloudinary-fileupload').bind('fileuploadprogress', function(e, data) {
$('.progress').attr({
style : "visibility:show",
});
$('.status_value').text('Uploading...');
});
</script>
The Cloudinary javascript plugin puts the preloaded resource URI in a hidden field.
See here.
From the above one sees that if the field already exists the javascript plugin will populate it. Otherwise, it will create it.
In order to retain that URI across invalid form submissions you should create a hidden field named according to the field name you specified for cloudinary_direct_upload_field and which is populated with the value from the failed submission.
Another way to work around the issue would be to submit the form using an AJAX call. That way the data on page is retained even if validation failed and resubmission is possible. See here for an example of how that may be done.
EDIT:
Version 1.0.12 of the Cloudinary Python client library now adds the hidden field when needed out of the box so resubmissions should work. See the change log.
EDIT 2:
In order to regenerate a preview image in case of form validation error you can add something like this to the javascript code you run on page load (assuming the field name in the form is "image"):
//If form validation failed have the posted preloaded URI from the earlier
//submission so we can show preview
//pull the value from the hidden field
var imageUri = $('#direct_upload input[name="image"]').val();
//preloaded image URI structure
//{resource_type}/{type}/v{version}/{filename}#{signature}
var regex = /^([^\/]+)\/([^\/]+)\/v(\d+)\/([^#]+)#([^\/]+)$/;
//if there is value and it matches the pattern:
if (imageUri && regex.test(imageUri)) {
var uriParts = regex.exec(imageUri);
var version = uriParts[3];
var filename = uriParts[4];
//reconstruct a viable source
var src = "v" + version + "/" + filename;
//generate a cloudinary image tag and add it to the 'preview' div
$(".preview").append(
$.cloudinary.image(src, {
transformation: "form_preview" //your named transformation
})
);
}

Get server URL for Ember DS.Model Class

In using Ember Data for my models, there are some cases where I need to work around the data limitations and access other quasi-restful URLs on my server.
For example, I have a Feed object that records a stream of data. For accessing the models I have a RESTful endpoint:
/feeds/:feed_id
In order to start and stop recording a feed, I need to send a PATCH to a url like:
/feeds/:feed_id?update_action=start
Subsequently I can reload my model and see the changes reflected therein.
In this case, I need to access $.ajax and the URL is the same as the one Ember would use. However, I can't figure out how to eke this information out of Ember.
So far, the best I can do is:
DS.Model.reopen
rootForModel: Ember.computed( ->
#.store.adapterForType(#).serializer.rootForType(#.constructor)
)
pluralRootForModel: Ember.computed( ->
#.store.adapterForType(#).serializer.pluralize(#get("rootForModel"))
)
Such that for an instance of App.FeedItem I can do:
this.get("rootForModel") # feed_item
this.get("pluralRootForModel") # feed_items
And I'm guessing this would stay in sync with any settings made in the Adapter etc.
Subsequently, I can call like:
$.ajax
url: #get("pluralRootForModel") + "/" + #get("id")
data:
update_action: "start"
type: "PATCH"
Is this totally out in left field? Is there a more direct way to compose these URLs?
Another (related issue) is getting the underscored name for a given model.
App.MyModelController => my_model_controller
I've done something like:
Ember.Object.reopenClass
###*
* The underscored name for this.
* i.e. App.MyClass -> my_class
* From an instance, use this.constructor.underscored_class_name()
* #return {String} This classname, underscored.
###
underscored_class_name: ->
_.underscored("#{#}".replace(/^.*?\./g, ""))
Is this crazy? Are there any better ways?
Check out buildURL in DS.RESTAdapter.
If you want to use underscores in server paths and keys, check out DS.ActiveModelAdapter (and its default serializer, DS.ActiveModelSerializer). This adapter has its own implementation of buildURL.

How can I send a file to the browser using Scalatra?

I'm using the scalatra-sbt-prototype. What would I have to modify, and where , to be able to serve files from a directory on my filesystem? Say for example , I would want to serve the file first.tar.gz from /home/downloads/first.tar.gz, and have it accessible as:
http://localhost:8080/first.tar.gz
For correctness, you may also want to set the contentType so the browser doesn't try to display it as text/html if you have that set in your before filter and the disposition header with the correct name. Most browsers will infer the filename from the url but just to be sure, you can set it explicitly.
get("/first.tar.gz") {
contentType = "application/octet-stream"
val file = new java.io.File("/home/downloads/first.tar.gz")
response.setHeader("Content-Disposition", "attachment; filename=" + file.getName)
file
}
Obviously the route is very static but will do what you want.
Returning a java.io.File to the browser, from an action, seems to accomplish this.