Copying one issue and its child issues is a natively built-in feature and thus works just fine.
But is there a way to do this multiple times?
Like re-creating one issue (including its children) twenty or fifty times?
Edit 2
This new functionality should be accessible via the Redmine interface and compatible to any browser.
It does not matter whether it is a completely new Plugin, an extension to the built-in copy feature, a call to a PHP-script or anything else.
Due to compatibility (networking, browsers etc.) I guess a completely server-side modification is the only way to go here.
What parts of the default plugin (as created in the voting tutorial) or a core element would have to be changed?
Where can I find the code for the native issue copy function?
Or - if all this is too complicated - how would I write my plugin to point to a PHP file that manipulates the SQL database directly?
Edit:
To clarify: just like the normal copy function (either in the context menu or the top-right link, I don't care) I want to copy one issue and its sub-issues n times.
To let the user set the amount n, any user number input may suffice, like a textbox, a pop-up etc.
I think the simplest way to do this is to start with redmine source modification.
Once it works you can move on and try to extract this feature into plugin.
Note, that I am not a ruby developer, so some things below are just my guesses. But I did few small redmine modifications like this before and hope that my thoughts can be useful.
It will also be easier if you familiar with some of MVC frameworks (for any language), because they mostly have a similar structure with routes, controllers, views and models.
The Idea
The link to copy single issue looks like this: //redmine.myserver.com/projects/myapp/issues/12407/copy.
My idea is to add a num_copies parameter to this link and use it in the code to create many copies.
You need no UI for that, once implemented the feature will work like this:
find the issue you need
choose the copy action for it
once the form opened, manually add ?num_copies=XX parameter into the URL (//redmine.myserver.com/projects/myapp/issues/12407/copy?num_copies=50) and press 'Enter' to reload the form
check the details and submit the form - it will create multiple copies according to the num_copies parameter
The Implementation Plan
Now, how to do this.
I am referring to the redmine mirror on github which looks fresh.
1) Find where the .../copy link is handled
When you open the form to copy the issue, you'll see form like this:
<form action="/projects/myapp/issues" class="new_issue" id="issue-form" method="post">
<input id="copy_from" name="copy_from" type="hidden" value="12407">
<div class="box tabular">
<div id="all_attributes">
...
</form>
Note the form action, it points to the /issues link and it will submit the copy_from parameter (this is ID of the issue we are copying).
2) Find the code which handles the form submission
We could first go and check through the config/routes.rb, but we can just guess that we need the controllers/issues_controller.rb
Search for the place where copy_from parameter is used.
You'll see the build_new_issue_from_params method.
Now search for its usages and you'll find this:
before_filter :build_new_issue_from_params, :only => [:new, :create]
From how it looks, I guess that it is called before both new and create actions.
Looking at new and create definitions, the new action renders the new issue form and the create action handles the form post.
3) Add the num_copies parameter to the form
Find the view file used by new issue action.
Here there is a template for the new issue form, try to add num_copies parameter similar to the copy_from:
<%= title l(:label_issue_new) %>
<%= call_hook(:view_issues_new_top, {:issue => #issue}) %>
...
<%= error_messages_for 'issue' %>
<%= hidden_field_tag 'copy_from', params[:copy_from] if params[:copy_from] %>
Here I am not 100% sure if it will just work if you add a similar line for `num_copies. You may also need to modify the route.
When done, you should have the new issue form like this:
<form action="/projects/myapp/issues" class="new_issue" id="issue-form" method="post">
<input id="copy_from" name="copy_from" type="hidden" value="12407">
<input id="copy_from" name="num_copies" type="hidden" value="50">
<div class="box tabular">
<div id="all_attributes">
...
</form>
4) Handle the num_copies parameter
It should be done in the create action:
def create
...
call_hook(:controller_issues_new_before_save, { :params => params, :issue => #issue })
#issue.save_attachments(params[:attachments] || (params[:issue] && params[:issue][:uploads]))
if #issue.save
...
end
Here you already have the #issue variable created in the build_new_issue_from_params method and what you need to do is to check if num_copies parameter is set and if it is set then copy / save the #issue in a loop to create additional copies.
I can't provide the exact code snippet for this, but it should not be very complex.
Check this code in the bulk_update method, it looks like what you need:
issue = orig_issue.copy({},
:attachments => copy_attachments,
:subtasks => copy_subtasks,
:link => link_copy?(params[:link_copy])
)
I think this specific plugin is not high priority for Redmine community.
But, you can write very easy API calling for Java, Python or other language to do what you exactly want.
Here, you can see API documentation how to list, create, update issues.
Issue API documentation
PS: You can leave your request in redmine community,
maybe you are lucky https://redmine.org/projects/redmine/issues
Related
I want to insert from Controller in the end of some view's code like this
"<"script> setInterval(function(){ alert("Hello"); }, 3000);"<"/script>
How to do this?
There's multiple ways to do this in PhalconPHP. Depending on your needs, you might be able to get away with just:
$js='setInterval(function(){alert("Hello");},3000);';
$this->view->js=$js;
then from the view, you'd do:
<script><?php echo $js; ?></script>
If you need to insert the JavaScript into your top-level index.phtml from a nested view, the way to accomplish this is to first edit your ControllerBase.php and define a new collection:
$this->assets->collection('footer');
Then add a reference to the footer collection from your top-level index.phtml file:
<body>
<?php echo $this->getContent(); ?>
<?php $this->assets->outputJs('footer'); ?>
</body>
You could also use output('footer') instead if you just wanted a dynamic place in the document you can insert HTML of any kind. Note that a collection specializes in managing CSS and JavaScript, hence the outputJS method, but can also handle miscellaneous code for other purposes. There's also outputCSS, outputInlineJs, outputInlineCss, outputInline, and simply output. See:
http://php-phalcon-docs.readthedocs.org/en/latest/api/Phalcon_Assets_Manager.html
Then edit your ControllerBase.php to initialize the asset to an empty collection:
$this->assets->collection('footer');
(if you skip this step, your code will see errors if your top-level index.phtml file tries to output the contents of a non-existent collection if you never write to it, so always initialize it to an empty collection so it exists.)
Finally, from the controller you want to use, you'd do:
$this->assets->collection('footer')->addInlineJs($js);
where $js is your inline JavaScript, excluding the script tags.
You can also work with external JavaScript files by using
->addJs(...). By default it will be relative to your application directory, inserting a / automatically. If you dislike this functionality, you can set the second parameter to false then it will allow you to specify your own leading / or point your resources at another domain.
As far as the assets you can add to a collection, see:
https://docs.phalconphp.com/en/latest/api/Phalcon_Assets_Collection.html
Note that you can also add assets to your collection from your view and the changes would still appear in your top-most index.phtml.
It is also worth noting that you don't need to actually use collections, you can simply use assets without a collection, but I think collections are more powerful in that you get to name them so there's another level of separation in case you need to manage more than one kind of collection of data.
In terms of what you're trying to accomplish, if you're just trying to give the user a message, this is what Phalcon's flash is for, not to be confused with Adobe Flash which is for playing videos. Phalcon's flash is for flashing messages to the user such as error messages, or your form submit successfully kind of messages. See:
https://docs.phalconphp.com/en/latest/reference/flash.html
If you're still confused what flash is, a demo of what it's output is, you can see in the screenshot here: https://docs.phalconphp.com/en/latest/_images/invo-2.png
That is output of ->error(...) and ->notice(...) respectively. The flash component keeps track of a collection of the messages you'd like to show the user. Then once you're ready to display them to the user you'd call:
<?php echo $this->flash->output(); ?> from your view. It is best to make this call from your top-most template or a template which is always included in your top-most template such as your navigation template so you can easily display messages to the user. It is also useful for debugging. I'd suggest using twitter bootstrap for styling the flash output.
Some sample applications which you might find useful:
https://github.com/phalcon/invo
https://github.com/phalcon/vokuro
https://github.com/phalcon/website
https://github.com/phalcon/forum
Further reading:
https://docs.phalconphp.com/en/latest/index.html
Hello all I'm very thankful for this community here, wouldn't know what to do without you all.
First of all, I'm not even sure if the title to this post is accurate; please read on. In a nutshell what I'm trying to do in Wordpress is create a 'reply' button that will be displayed on the individual post's page. When someone clicks on this 'reply' button it will take them to a different WP page that is using a private messaging plugin. On this page I would like the 'to:' field to automatically know who to reply to (author of the post).
Now here's my question. Is this accomplished by "passing a variable" from first page to the second or is there another way to do this?
I'm not asking for specific code help so please don't tell me to go talk with the plugin developer. I'm just trying to get a general idea of how something like can be accomplished so that I can do some research myself.
At the very least, If someone get give me a starting point for me to do some google research that would be all I need. Being fairly new I don't even know what phrase I should be googling for.
Yes, you can do that by implementing simple wp plugin. First of all you need to know that, there are lots of wp specific functions. You can use the_content for putting your reply link after post content, and get_author_meta in order to get post's author email for putting it in your custom link. I know, you don't want to talk about code, but I can give you sample example; In order to apply this functionality on all post, you can simply implement a plugin.
Edit: For redirecting to Private Messaging plugin's send page with prepopulated recipient field, I have updated get_the_author_meta('email') with get_the_author_meta('user_login'). Now, you can go to mail send page, by clicking Reply link
add_filter('the_content', 'add_custom_link');
function add_custom_link($content) { // You can think that $content => individual post
if(is_single()) {
$content .= 'Reply to this post';
}
return $content;
}
Save this code in a php file and zip it.Then, upload it to your wp site as plugin. And you will see your custom link at the end of your posts. Do not forget to update variables in plugin according to your needs(for example reply url domain)
Here is a working plugin demo: http://huseyinbabal.eu01.aws.af.cm/?p=1
Create a form that posts to the secondary page.
Use a hidden form field to pass the post ID
Make sure you prefix the form fields so your $_POST variable doesn't conflict with any other core/plugin variables
On the secondary page: make sure you sanitize that user input before you do anything else
with it
use the sanitized post id to look up the post's author, without
having to expose the author's email in the url.
Your Form should look something like so:
<form action="url-of-page-2" method="POST">
<input type="hidden" name="myprefix_id" value="<?php echo get_the_ID();?>">
<input type="submit" value="reply">
</form>
The error in the title is visible only in firebug. Everything from where I put the recaptcha element on down, is not shown on the page, though is present in the page-source (Mozilla and Opera) - though no error is shown in firebug.
So far, based on others solutions, I have tried reversing the keys (public and private, though they are clearly identified), generating a global-key-pair and using those, and even hard-coding the values into the recaptcha.rb initializer file versus using system-vars. No luck in any cases in dev or production. Also tried suppressing the 'noscript' part, with no change.
The Gem-Generated Page Source reads:
<script type="text/javascript" src="//www.google.com/recaptcha/api/challenge?k=[" mypublickeyhere", "myprivatekeyhere", false]&lang="></script>
<noscript>
<iframe src="//www.google.com/recaptcha/api/noscript?k=["mypublickeyhere", "myprivatekeyhere", false]" height="300" width="500" style="border:none;"></iframe><br/>
<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
<input type="hidden" name="recaptcha_response_field" value="manual_challenge"/></noscript>
Why is my private key visible in the page-source? All that code comes from putting this in my view:
<%= recaptcha_tags %>
Edit: Made some progress, many hours in, by force-feeding the keys in the form and controller with:
<%= recaptcha_tags :public_key => 'mypublickeyhere' %>
and
if ( verify_recaptcha :private_key => 'myprivatekeyhere' )
Which gets the recaptcha to show up on the form, and keeps my private-key from being spammed to the page-code by the plugin as it does in 'default' mode.
Unfortunately, even if captcha is entered correctly, we get a NEW Error, "invalid-request-cookie".
Is there a single example of using this plugin in Rails 3, with full working form and controller code?
More Info for other sufferers:
Google Says this error means: "The challenge parameter of the verify script was incorrect."
On another page, if you search for "challenge parameter," to find out whatever that is, Google says: "recaptcha_challenge_field is a hidden field that describes the CAPTCHA which the user is solving. It corresponds to the 'challenge' parameter required by the reCAPTCHA verification API."
So why is the plugin not providing the correct challenge parameter as it should? Perhaps I need to pass something somewhere - but what and where? Again, a simple example would be great.
0.0. Setting the Variables - an aside:
Use ENV['key'] to keep your keys out of the codebase (though you can hardcode them in /config/environments/development.rb and then not include this file on your production server (for Heroku, add to gitignore in your push folder).
I added this to my development.rb file
# Set variables for Recaptcha on Localhost
ENV['RECAPTCHA_PUBLIC_KEY'] = 'mypublickeyhere'
ENV['RECAPTCHA_PRIVATE_KEY'] = 'myprivatekeyhere'
You will put your real key values in place of mybpublickeyhere and myprivatekeyhere.
You could also set ENV variables on your dev-machine. I prefer not to add that clutter, as this machine is used to develop many sites at once.
If deploying to Heroku, learn how to set these ENV variables here:
http://devcenter.heroku.com/articles/config-vars
1.0 Get a set of global-keys, not tied to any particular domain, and use these for testing. After eliminating that potential problem, when all is working, put in your domain-specific keys, on your production machine, and re-test.
2.0 Don't use the 'default' method. From what I can tell, it simply does not work - maybe it once did and Google changed something - I don't know, but it may/will give you the dreaded "Input error: k: Format of site key was invalid" AND will reveal your private key to anyone who views the page-source.
The solution is to force-feed the keys into the form and controller. So, in your form this will look like:
<%= recaptcha_tags :public_key => ENV['RECAPTCHA_PUBLIC_KEY'] %>
3.0 In your controller you will test for true; but again, force-feed the private key like this:
if ( verify_recaptcha :private_key => ENV['RECAPTCHA_PRIVATE_KEY'] )
... your success code here
else
... your fail code here
end
4.0 Placement of the tag in the form is important. The Devise docs refer to this gem, and provide actual example code of using this gem:
http://github.com/plataformatec/devise/wiki/How-To:-Use-Recaptcha-with-Devise
They say to put the recaptcha_tags immediately above the submit button code. This is important. I had to put it within:
<div class="form-actions">
... along with the button
Other sources report that surrounding HTML can break things in mysterious ways, so you may have to experiment for awhile (hope you don't have deadlines, or anything). These 'placement' issues were the culprit with the 'invalid-request-cookie' error I received.
I hope these guidelines shorten your development time.
I have another question. I am sure that it is really really easy to answer to you but I just don´t know how to do it.
I am using Ruby on Rails 3.2.9.
In a view I want to define some variables which works fine like this:
<p>
<b>Artikelnummer:</b>
<%= #artikel.artikelnummer %>
</p>
<%= $aktArtNr = #artikel.artikelnummer %>
But now I want to save some User input (which should not cause a controller action or something else) in a variable - and I don´t know how to do it.
P.e. I want to save the "thing" that the user types into this form
<form name="Menge">
<input type="text">
</form>
in a variable called $aktMenge
It must be so easy but i´ve been trying this for a long time without success (but with getting a headache...)
P.S. after I just call a controller action which should do something with the variable...
Thanks a lot!
I'm struggling to see what you're trying to do. My suggestion would be to have a play around with Rails scaffolding so you can see how this works from the controller through to the views. e.g. open a terminal and try (maybe in a new project):
rails generate scaffold artikel name:string content:text ref_number:integer
rake db:migrate
Then go and look in your browser at "localhost:[port_no]/artikels" and you should be able to create, update and delete records through the web interface. Then go and have a look at the code generated to see if you can relate it to what you're doing.
Once again sorry for being new about all this RESTful stuff. I realized that due to the fact that i didn´t really know what exactly rails can do, i didn´t answer the right Question...
But this solved my problem:
Rails getting single values from request
The problem is that i have a remote form that, based on condition, id like to convert to a non-remote form (using UJS), and then submit.
note the form has a file upload.
Here's the details: I have initially rendered the remote form using
= form_for #myobj, :url => {:action=>"remoteAction", :controller=>"myobjects"}, :remote => true do |f|
... (f.fields....)
which produces the HTML:
<form id="new_myobj" class="new_myobj" method="post" accept-charset="UTF-8" data-remote="true" action="/remoteAction">
when i click submit, as expected, the form is submitted 'AS JS'.
in the controller action, i am doing some validation of the fields inside the submitted form.
If all the validations pass, i execute the following .js.haml template:
$('form#new_myobj').removeAttr("data-remote");
$('form#new_myobj').attr('enctype', 'multipart/form-data');
$('form#new_myobj').attr('action', '/myobjects/regularAction');
which successfully changes the HTML on the page (witnessed via Firebug) to:
<form id="new_myobj" class="new_myobj" method="post" accept-charset="UTF-8" enctype="multipart/form-data" action="/myobjects/regularAction">
since the form contains an f.file_field, i have to submit as multipart so the image can be uploaded, and i cannot submit 'AS JS'
now, when i click submit, the controller action 'regularAction' is indeed called, but its still 'AS JS'
the question is, what else do i need to change in the HTML so the form can be submitted non-xhr? is it related to the headers?
jQuery is a bit tricky with the data attributes since it both
reads the HTML5 data tags as well as its own storage bound to the
DOM element, that is also called data. When writing to an attribute
that value gets copied into jQuerys own data storage (presumably
when data("remote") is being called).
However, this only happens
if jQuery’s data is empty for that name. Thus setting the attribute will only work once, after that the "cached" value is being used
even if the attribute changes. In order to really get rid of the
value, we need to remove the attribute and jQuerys own storage
method in that order. The reason is that there’s a high-level
(element.removeData(…)) function and a low level one (jQuery.
removeData(element, …)). The former re-reads the HTML5 data
attribute and stores it in jQuery’s own storage. Using the rather
unusual low level function obviously works as well.
Also, we do really need to remove the attribute -- setting it to
false is not enough since Rails only checks if form.data('remote')
is not undefined (look for it in jquery_ujs.js).
TL;DR:
attr("data-remote") != data("remote")
These two lines make a form non-remote (again). Order matters.
$("form").removeAttr("data-remote");
$("form").removeData("remote");
It’s documented, if you actually know what you’re looking for:
http://api.jquery.com/jQuery.data/ (low level function)
http://blog.madebydna.com/all/code/2011/12/05/ajax-in-rails-3.html
StackOverflow doesn’t allow me to post more than two links, but you can guess the removeData one. The high-level functions are linked from the low level ones.
Avoiding the token authenticity error in Rails 4+:
As Stan commented below, just doing the above will fail with an InvalidAuthenticityToken error. The workaround is easy though, see here for details: https://stackoverflow.com/a/19858504/1684530
The problem is that your approach to disable the Ajax submission isn't quite correct. You need to unbind the JavaScript events that have already been added by rails.js (Rails UJS adapter) to the form.
You can do that by:
$('form#new_myobj').unbind() to unbind all events attached to the form. You also need to $('form#new_myobj').removeAttr('data-remote') and $('form#new_myobj').removeAttr('data-type') to remove data-remote and data-type attributes (if existent).