Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to use undo and redo properly in editor #2602

Closed
bcatly opened this issue Mar 1, 2021 · 8 comments
Closed

Unable to use undo and redo properly in editor #2602

bcatly opened this issue Mar 1, 2021 · 8 comments

Comments

@bcatly
Copy link

bcatly commented Mar 1, 2021

Describe the bug
Whilst using the website in WYSIWYG editor mode, I am unable to use the undo and redo correctly. I can undo once, but after that it seems to have forgotten all the settings.

Steps To Reproduce
Create a new page in any book. Type a couple lines of words then try to press undo and redo.

Before I press undo
image

After pressing undo
image

As you can see, the redo button is still greyed out, like I have never pressed it. I also cannot undo any more steps or redo the step I just did. If I continue onwards from here, it seems I gain the ability to undo 1 time again.

Expected behavior
I expect to be able to use the redo and undo button reliably. At least for a couple steps as what is the case with other text editors.

Screenshots
Screenshots attached above.

Your Configuration (please complete the following information):

  • Exact BookStack Version (Found in settings): V 0.31.6
  • PHP Version: PHP 7.4.3
  • Hosting Method (Nginx/Apache/Docker): Apache
@bcatly
Copy link
Author

bcatly commented Mar 3, 2021

After further usage of bookstack, I have now noticed that there are some pages affected by it, and other pages which are not affected by the bug I have mentioned. If there's anything you would like me to provide to give you a greater insight as to what the issue might be, please let me know and I'd be more than happy to provide.

@ssddanbrown
Copy link
Member

Hi @bcatly,
Confirmation of your browser and operating system would help here. In addition, Some sample content would be ideal. If you can re-produce this with content you can share, then sharing the HTML source content of the page would be ideal. This can be seen by using the source-code button that's towards the right of the editor toolbar when editing a page.

@bcatly
Copy link
Author

bcatly commented Mar 8, 2021

Hi @ssddanbrown

Thanks for the help! I am using Firefox and I am on a Windows 10 Operating System.

As for the source code you have requested I have input it below. More than shareable content, as it's only my progress in understanding how to use bash! Hope there's something there that can prove useful to resolving the issue. If you need anything else, please do let me know.

<p id="bkmrk-"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/Jft60GnP93TokCyz-image-1614632092052.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/Jft60GnP93TokCyz-image-1614632092052.png" alt="image-1614632092052.png" width="665" height="234" /></a></p>
<p id="bkmrk-%C2%A0">&nbsp;</p>
<p id="bkmrk-these-work-in-your-t">These work in your typical format where you test for a condition, and if it is true, the code will continue. You can also add an else statement, so that if the situation is false, it will execute a different statement.</p>
<p id="bkmrk--0"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/yzjqywgcciDHK4SC-image-1614632214524.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/yzjqywgcciDHK4SC-image-1614632214524.png" alt="image-1614632214524.png" width="778" height="171" /></a></p>
<p id="bkmrk-%C2%A0-0">&nbsp;</p>
<p id="bkmrk-%C2%A0-1">&nbsp;</p>
<p id="bkmrk--1"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/TVD0QHjb7fxZwtkO-image-1614632938260.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/TVD0QHjb7fxZwtkO-image-1614632938260.png" alt="image-1614632938260.png" width="455" height="176" /></a></p>
<p id="bkmrk-the-above-is-an-exam">The above is an example of using extended tests to action the following test.</p>
<p id="bkmrk-%C2%A0-2">&nbsp;</p>
<p id="bkmrk--2"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/toQkaE9iKXiXOzBe-image-1614632986875.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/toQkaE9iKXiXOzBe-image-1614632986875.png" alt="image-1614632986875.png" width="484" height="215" /></a></p>
<p id="bkmrk-this-is-an-alternati">This is an alternative method to do the same test, but with an arithmetic evaluation. It would make more sense to use an arithemetic evaluation in this case, however, depending on the script, it would be best to choose the one which adds to the uniformity of the code (if you are collaborating with someone).</p>
<p id="bkmrk-it-is-also-to-expand"><strong>it is also to expand the above into further conditions by adding an elif statement. </strong></p>
<p id="bkmrk--3"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/WXjalJo8kXukOyEA-image-1614633216687.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/WXjalJo8kXukOyEA-image-1614633216687.png" alt="image-1614633216687.png" /></a></p>
<p id="bkmrk-the-above-is-a-simpl">the above is a simple example of an elif condition.</p>
<pre><code class="language-shell">#Oneliner example of an if statement
if [ $a -lt $b ]; then echo "yes" fi</code></pre>
<h4 id="bkmrk-loops-in-bash">Loops in Bash</h4>
<ul id="bkmrk-while-loops-run-whil">
<li>While loops run while a condition is true</li>
<li>Until loops run until a condition is true</li>
</ul>
<p id="bkmrk--4"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/q348NAobYpWci4HE-image-1614678130112.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/q348NAobYpWci4HE-image-1614678130112.png" alt="image-1614678130112.png" width="432" height="212" /></a></p>
<p id="bkmrk-%C2%A0-4">&nbsp;</p>
<p id="bkmrk--5"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/agjmqwUikKqoYj9n-image-1614678160629.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/agjmqwUikKqoYj9n-image-1614678160629.png" alt="image-1614678160629.png" width="268" height="228" /></a></p>
<p id="bkmrk-in-this-line-of-code">In this line of code above, whilst n is less than 10, it will continue to run the code within the do statement.</p>
<p id="bkmrk-inside-of-the-do-sta">Inside of the do statement, we have (( n++ )). This increments n by 1, and therefore, once n has reached 10, it shall stop. In this case, the output shall be 1 till 9.</p>
<p id="bkmrk-%C2%A0-5">&nbsp;</p>
<p id="bkmrk--6"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/rWdJbeFyMoc79J5N-image-1614678324589.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/rWdJbeFyMoc79J5N-image-1614678324589.png" alt="image-1614678324589.png" width="484" height="182" /></a></p>
<p id="bkmrk-%C2%A0-6">&nbsp;</p>
<p id="bkmrk--7"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/e4H1lkg8YtXwAzco-image-1614678377028.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/e4H1lkg8YtXwAzco-image-1614678377028.png" alt="image-1614678377028.png" /></a></p>
<p id="bkmrk-the-while-loop-is-ve">The while loop is very similar to the While loop. The only difference here is that the condition has changed from, "whilst it is true" to "until it is true".</p>
<p id="bkmrk-therefore%2C-the-outpu">Therefore, the output for both of these would be the same.</p>
<p id="bkmrk--8"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/83AYTJrBaMrL7Nte-image-1614679009529.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/83AYTJrBaMrL7Nte-image-1614679009529.png" alt="image-1614679009529.png" width="192" height="439" /></a></p>
<p id="bkmrk-%C2%A0-3">&nbsp;</p>
<h4 id="bkmrk-introducing-for-loop">Introducing for loops</h4>
<p id="bkmrk--9"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/EBGqyhTCYzhSSk43-image-1614679435997.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/EBGqyhTCYzhSSk43-image-1614679435997.png" alt="image-1614679435997.png" width="571" height="203" /></a></p>
<p id="bkmrk-%C2%A0-8">A for loop is very useful, as it can reiterate a list of items. This can be useful when going through files within a directory, if you need to make mass modifications. Or possible to be used with an array.</p>
<p id="bkmrk--10"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/nu7Ssg7V39KJE40C-image-1614679624729.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/nu7Ssg7V39KJE40C-image-1614679624729.png" alt="image-1614679624729.png" width="246" height="166" /></a></p>
<p id="bkmrk-in-the-example-above">In the example above, we use brace expansion to get the numbers 1 to 100. It will then echo out each number in sequence.</p>
<p id="bkmrk-%C2%A0-9">&nbsp;</p>
<p id="bkmrk--11"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/XHsYkzFBzVz5JyR7-image-1614679808004.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/XHsYkzFBzVz5JyR7-image-1614679808004.png" alt="image-1614679808004.png" width="366" height="120" /></a></p>
<p id="bkmrk-we-can-also-do-for-l">We can also do for loops in the following way with arithmetic evaluations. This first works by setting i to 1. The middle section is then the test that it is looking for and lastly, we have an increment for i.</p>
<p id="bkmrk-look-into-the-above-"><strong>look into the above a bit more. Not too sure how this works.</strong></p>
<p id="bkmrk-%C2%A0-10">&nbsp;</p>
<p id="bkmrk--12"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/KIEbBmuOSuTqhycL-image-1614680750960.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/KIEbBmuOSuTqhycL-image-1614680750960.png" alt="image-1614680750960.png" width="465" height="164" /></a></p>
<p id="bkmrk-%C2%A0-11">As stated above, it is indeed possible to use the for loop with arrays also (Ha! I'm psychic).</p>
<p id="bkmrk-in-this-example%2C-we-">In this example, we have an array with the values apple, banana and cherry.</p>
<p id="bkmrk-it-then-uses-these-v">It then uses these values to echo out the fruits.</p>
<p id="bkmrk--13"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/RWzVeE1xyVVgVwDh-image-1614680024918.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/RWzVeE1xyVVgVwDh-image-1614680024918.png" alt="image-1614680024918.png" width="356" height="131" /></a></p>
<p id="bkmrk-as-we-can-see-above%2C">As we can see above, these would be the output for it.</p>
<p id="bkmrk-%C2%A0-12">&nbsp;</p>
<p id="bkmrk-whilst-we-can-use-th">Whilst we can use these for these specific scenarios. It is also possible to use the for loop with a command to get a list of items. I.e. we can do the below.</p>
<p id="bkmrk--14"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/0QafgMfWKJySHrww-image-1614680219611.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/0QafgMfWKJySHrww-image-1614680219611.png" alt="image-1614680219611.png" width="345" height="103" /></a></p>
<p id="bkmrk-%C2%A0-13">&nbsp;</p>
<h4 id="bkmrk-selecting-behavior-u">Selecting behavior using case</h4>
<ul id="bkmrk-checks-an-input-agai">
<li>Checks an input against a set of prefined values</li>
<li>Runs code when an input matches a condition</li>
</ul>
<pre><code class="language-shell">#!/bin/bash

animal="dog"
case $animal in
	cat) echo "Feline";;		#If the value is cat, it will output feline
    dog|puppy) echo "Canine";;	#If the value is either dog or puppy, it shall output canine. Note that | allows use to put a list of possible values.
    *) "No match!"				#Catch all statement if nothing is matched to the predefined values we have provided.
esac

</code></pre>
<p id="bkmrk-%C2%A0-14">&nbsp;</p>
<p id="bkmrk-%C2%A0-16">As we can see here, case statements are a good way to shorten what if statements would be like. Especially if it is only a one-liner that needs to be outputed. It is important to note that to end the script we must write <strong>esac. </strong>This is <strong>case</strong> backwards!</p>
<p id="bkmrk-i-will-have-to-exper">I will have to experiment if it can do more than just one liners.</p>
<p id="bkmrk--15"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/irUYdzzpkz2ipIA4-image-1614681111020.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/irUYdzzpkz2ipIA4-image-1614681111020.png" alt="image-1614681111020.png" /></a></p>
<p id="bkmrk-as-we-can-see-from-t">As we can see from the code above, we can indeed have more than one line whilst using the case statement. This makes it into a very powerful tool, when we are looking for predefined values.</p>
<p id="bkmrk-%C2%A0-15">&nbsp;</p>
<h4 id="bkmrk-%C2%A0-17">Using functions</h4>
<p id="bkmrk--16"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/2I4MawrivTrVSXis-image-1614682541749.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/2I4MawrivTrVSXis-image-1614682541749.png" alt="image-1614682541749.png" width="525" height="234" /></a></p>
<p id="bkmrk-%C2%A0-18">&nbsp;</p>
<p id="bkmrk-functions-are-a-bril">Functions are a brilliant piece of code if you need to run a specific set of command multiple times. This helps you to mitigate typing mistakes and also improves the readability of your code. The most important part about a function is it's ability to take in arguments. This allows us to provide information that can then be subsituted within the code itself.</p>
<pre><code class="language-shell">#!/bin/bash

 greet () {
     echo "Hi there, $1"
 }
 greet Scott</code></pre>
<p id="bkmrk-as-we-can-see-in-the">As we can see in the above code, we can use $1 to symbolise the first argument passed to the function.</p>
<p id="bkmrk-%C2%A0-19">&nbsp;</p>
<p id="bkmrk--17"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/RRTr2CkeaHWigdqi-image-1614683062276.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/RRTr2CkeaHWigdqi-image-1614683062276.png" alt="image-1614683062276.png" width="507" height="144" /></a></p>
<p id="bkmrk-%C2%A0-20">The two above variables are useful functions to take note of.</p>
<pre><code class="language-shell"> #!/bin/bash

 numberthing() {
     declare -i i=1
     for f in $@; do
         echo "$i: $f"
         (( i++ ))
     done
     echo "This counting was brought to you by $FUNCNAME."
 }

 numberthing $(ls /)
 echo
 numberthing pine birch maple spruce</code></pre>
<p id="bkmrk--18"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/ChnU35pE4x2NKoYM-image-1614683513891.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/ChnU35pE4x2NKoYM-image-1614683513891.png" alt="image-1614683513891.png" width="331" height="364" /></a></p>
<p id="bkmrk-as-we-can-see-from-t-0">As we can see from the above code and output, this shows how the $@ can be used to output all things that is provided to the function. In this case, it provided us with a numbered list of items from within the root directory.</p>
<p id="bkmrk-%C2%A0-21">&nbsp;</p>
<p id="bkmrk--19"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/Gm2Bl49VSz0ShsQq-image-1614683711517.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/Gm2Bl49VSz0ShsQq-image-1614683711517.png" alt="image-1614683711517.png" /></a></p>
<p id="bkmrk-another-important-th">Another important thing to note is that variables set within a function is still considered as a global function. This means that you can call upon that variable at any time.</p>
<p id="bkmrk-however%2C-if-you-use-">However, if you use the word <strong>local, </strong>it ensures that this keyword can only be used inside the function.</p>
<p id="bkmrk-%C2%A0-22">&nbsp;</p>
<h4 id="bkmrk-reading-and-writing-">Reading and writing text files</h4>
<p id="bkmrk--20"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/MiYEs81wgKXcYQqp-image-1614684598795.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/MiYEs81wgKXcYQqp-image-1614684598795.png" alt="image-1614684598795.png" width="618" height="225" /></a></p>
<p id="bkmrk-%C2%A0-23">&nbsp;</p>
<p id="bkmrk--21"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/SZl7sjyfWE59hvjh-image-1614685188316.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/SZl7sjyfWE59hvjh-image-1614685188316.png" alt="image-1614685188316.png" width="526" height="107" /></a></p>
<p id="bkmrk-in-this-example%2C-we--0">In this example, we have an output redirection, that inputs the following lines into a file called textfile.txt.</p>
<p id="bkmrk-as-there-is-a-%3E%3E%2C-th">As there is a &gt;&gt;, this appends the words to a txt. Thereby, it will output all the test from 1 to 5.</p>
<p id="bkmrk-%C2%A0-24">&nbsp;</p>
<p id="bkmrk--22"><a href="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/qQVA1Q4tUpSTJv1o-image-1614685635333.png" target="_blank" rel="noopener"><img src="https://bookstack.sleepygon.com/uploads/images/gallery/2021-03/scaled-1680-/qQVA1Q4tUpSTJv1o-image-1614685635333.png" alt="image-1614685635333.png" width="477" height="96" /></a></p>
<p id="bkmrk-the-above-was-not-ex">The above was not explained very well in the course, however, the read parameter, takes the contents from the txt file that is directed into the done section. This then takes line by line as the parameter f, in this case. When there is no more lines to read, the while statement is then no longer true and thus the loop finishes.</p>
<p id="bkmrk-%C2%A0-25">&nbsp;</p>
<p id="bkmrk-%C2%A0-26">&nbsp;</p>
<p id="bkmrk-fortune-example-for-">Fortune example for challenge.</p>
<pre><code class="language-shell">#!/usr/bin/env bash

# A fortune-telling game

echo -e "\t\t   Welcome to the "
echo -e "\t\t🔮 \033[5mMyStIcAl sPhErE\033[0m 🔮"
echo

waitingnumber=$(( 0 + $RANDOM % 3 ))
mysterynumber=$(( 1 + $RANDOM % 10 ))

declare -a fortunes=(
	"You are likely to achieve the outcome you seek."
	"Today is not a good day to do that."
	"While it might seem unlikely, your chances are good."
	"If you believe you will be successful, that's half the battle."
	"If you cared enough to ask, you care enough to make it happen."
	"I think you already know the answer to that."
	"Stop wondering and start doing!"
	"Yes, sure, whatever, I'm busy."
	"Next Thursday might be a better day to do that."
	"Sure, but what will the neighbors think?"
)

case $waitingnumber in
	0) sleep 1; echo "One moment please..."; sleep 1;;
	1) sleep 1; echo "Your fortune will be along shortly..."; sleep 2;;
	2) sleep 1; echo "Preparing your fate..."; sleep 1;;
	3) sleep 1; echo "The veil of mystery is dark today..."; sleep 3;;
esac

echo
echo ${fortunes[mysterynumber]}
echo</code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>This is a test file</p>
<p>Another test file</p>
<p>&nbsp;</p>
<p id="bkmrk-%C2%A0-27">&nbsp;</p>```

@bcatly
Copy link
Author

bcatly commented Mar 24, 2021

HI there! Any chance you were able to replicate this issue on your side?

@bcatly
Copy link
Author

bcatly commented Mar 25, 2021

@ssddanbrown I think I may have found a correlation to what causes the issue.

It appears to be that any page I have which contains a code block, all fall for the same no undo situation.

When I tested this with a page I did not add a code block on, everything seems to work just fine.

Edit: I can confirm that the issue is in relation to code blocks. I tried deleting the codeblock from a page and saved it. After trying the undo and redo, it works again.

Any chance there would a solution to this issue?

@ssddanbrown
Copy link
Member

Hi @bcatly,
Sorry for the late response, Been meaning to test this but had trouble getting round to it.

Thanks for the extra examples and investigation done above, I can confirm I can replicate this on my dev instance when a code block is in the page. I've marked this for the next patch release so I don't forget to address it.

ssddanbrown added a commit that referenced this issue Apr 19, 2021
…states

Only used an undo transaction on startup and added a small delay
to codeMirror parsing on SetContent's to help avoid
the rendering activities getting caught in undoManager states.
Seemed to improve things a lot in Firefox & chrome on my dev machine.

For #2602
@ssddanbrown
Copy link
Member

@bcatly I've just released v21.04.1 with some changes to make the undo/redo become much more stable around code blocks. The changes seemed to work well on my dev instances but if you could test and confirm it improves the experience on your instance, that would be great.

@ssddanbrown
Copy link
Member

ssddanbrown commented Apr 26, 2021

I'll close this off but if you continue to frequently have problems after upgrading feel free to let me know or open a new issue referencing this one if I'm unresponsive here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants