mirror of
https://github.com/aelve/guide.git
synced 2024-11-23 12:15:06 +03:00
Merging for item notes
This commit is contained in:
parent
392d1c592a
commit
8f4d2dd417
52
src/JS.hs
52
src/JS.hs
@ -405,12 +405,28 @@ makeTraitEditor =
|
||||
$(sectionNode).append(area, br, cancelBtn, markdown);
|
||||
|]
|
||||
|
||||
-- | Dynamically creates a 'View.markdownEdito' (but specifically for item
|
||||
{- Note [blurb diffing]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A note on why we need 'empty' in 'makeItemNotesEditor'.
|
||||
|
||||
Assume that the notes are empty. The text in the area, therefore, will be some default blurb (“# Links, #Imports, #Usage”, etc). Suppose the user edits it. What will be sent to the server?
|
||||
|
||||
* original: blurb
|
||||
* our version: modified blurb
|
||||
|
||||
What will happen next? The server will compare it to the value currently at the server (i.e. an empty string), and think that the blurb *was* on the server but got deleted while the client was doing editing. This is wrong, and will result in a diff popup comparing an edited blurb to an empty string. To prevent this, we pass 'empty' to 'makeItemNotesEditor' – if we're using a blurb, we'll pass an empty string as the original.
|
||||
|
||||
-}
|
||||
|
||||
-- | Dynamically creates a 'View.markdownEditor' (but specifically for item
|
||||
-- notes). See Note [dynamic interface].
|
||||
makeItemNotesEditor :: JSFunction a => a
|
||||
makeItemNotesEditor =
|
||||
-- See Note [blurb diffing]
|
||||
makeJSFunction "makeItemNotesEditor"
|
||||
["notesNode", "sectionNode", "textareaUid", "content", "itemId"]
|
||||
["notesNode", "sectionNode", "textareaUid",
|
||||
"empty", "content", "itemId"]
|
||||
[text|
|
||||
$(sectionNode).html("");
|
||||
area = $("<textarea>", {
|
||||
@ -423,7 +439,7 @@ makeItemNotesEditor =
|
||||
"value" : "Save",
|
||||
"type" : "button" })[0];
|
||||
saveBtn.onclick = function () {
|
||||
submitItemNotes(notesNode, itemId, area.value); };
|
||||
submitItemNotes(notesNode, itemId, empty ? "" : content, area.value); };
|
||||
// Can't use $()-generation here because then the <span> would have
|
||||
// to be cloned (since we're inserting it multiple times) and I don't
|
||||
// know how to do that.
|
||||
@ -508,16 +524,28 @@ submitItemEcosystem =
|
||||
|
||||
submitItemNotes :: JSFunction a => a
|
||||
submitItemNotes =
|
||||
makeJSFunction "submitItemNotes" ["node", "itemId", "s"]
|
||||
makeJSFunction "submitItemNotes"
|
||||
["node", "itemId", "original", "ours"]
|
||||
[text|
|
||||
$.post("/haskell/set/item/"+itemId+"/notes", {content: s})
|
||||
.done(function (data) {
|
||||
$.post({
|
||||
url: "/haskell/set/item/"+itemId+"/notes",
|
||||
data: {
|
||||
original: original,
|
||||
content: ours },
|
||||
success: function (data) {
|
||||
$.magnificPopup.close();
|
||||
$(node).replaceWith(data);
|
||||
switchSection(node, "expanded");
|
||||
// Switching has to be done here and not in 'Main.renderItemNotes'
|
||||
// because $.post is asynchronous and will be done *after*
|
||||
// switchSection has worked.
|
||||
switchSection(node, "expanded"); },
|
||||
statusCode: {
|
||||
409: function (xhr, st, err) {
|
||||
modified = xhr.responseJSON["modified"];
|
||||
merged = xhr.responseJSON["merged"];
|
||||
showDiffPopup(ours, modified, merged, function (x) {
|
||||
submitItemNotes(node, itemId, modified, x) }); } }
|
||||
});
|
||||
// Switching has to be done here and not in 'Main.renderItemNotes'
|
||||
// because $.post is asynchronous and will be done *after*
|
||||
// switchSection has worked.
|
||||
|]
|
||||
|
||||
-- | Add a pro to some item.
|
||||
@ -554,8 +582,8 @@ submitTrait =
|
||||
$.post({
|
||||
url: "/haskell/set/item/"+itemId+"/trait/"+traitId,
|
||||
data: {
|
||||
original : original,
|
||||
content : ours },
|
||||
original: original,
|
||||
content: ours },
|
||||
success: function (data) {
|
||||
$.magnificPopup.close();
|
||||
$(node).replaceWith(data);
|
||||
|
19
src/Main.hs
19
src/Main.hs
@ -475,12 +475,21 @@ setMethods = Spock.subcomponent "set" $ do
|
||||
lucidIO $ renderItemEcosystem item
|
||||
-- Item notes
|
||||
Spock.post (itemVar <//> "notes") $ \itemId -> do
|
||||
original <- param' "original"
|
||||
content' <- param' "content"
|
||||
invalidateCache' (CacheItemNotes itemId)
|
||||
(edit, item) <- dbUpdate (SetItemNotes itemId content')
|
||||
addEdit edit
|
||||
category <- dbQuery (GetCategoryByItem itemId)
|
||||
lucidIO $ renderItemNotes category item
|
||||
modified <- view (notes.mdText) <$> dbQuery (GetItem itemId)
|
||||
if modified == original
|
||||
then do
|
||||
invalidateCache' (CacheItemNotes itemId)
|
||||
(edit, item) <- dbUpdate (SetItemNotes itemId content')
|
||||
addEdit edit
|
||||
category <- dbQuery (GetCategoryByItem itemId)
|
||||
lucidIO $ renderItemNotes category item
|
||||
else do
|
||||
setStatus HTTP.status409
|
||||
json $ M.fromList [
|
||||
("modified" :: Text, modified),
|
||||
("merged" :: Text, merge original content' modified)]
|
||||
-- Trait
|
||||
Spock.post (itemVar <//> traitVar) $ \itemId traitId -> do
|
||||
original <- param' "original"
|
||||
|
@ -810,6 +810,8 @@ renderItemInfo cat item = cached (CacheItemInfo (item^.uid)) $ do
|
||||
let bg = hueToDarkColor $ getItemHue cat item
|
||||
let thisId = "item-info-" <> uidToText (item^.uid)
|
||||
this = JS.selectId thisId
|
||||
let bodyNode = JS.selectChildren (JS.selectParent this)
|
||||
(JS.selectClass "item-body")
|
||||
div_ [id_ thisId, class_ "item-info",
|
||||
style_ ("background-color:" <> bg)] $ do
|
||||
|
||||
@ -836,8 +838,6 @@ renderItemInfo cat item = cached (CacheItemInfo (item^.uid)) $ do
|
||||
section "editing" [] $ do
|
||||
-- When the info/header node changes its group (and is hence
|
||||
-- recolored), item's body has to be recolored too
|
||||
let bodyNode = JS.selectChildren (JS.selectParent this)
|
||||
(JS.selectClass "item-body")
|
||||
let formSubmitHandler formNode =
|
||||
JS.submitItemInfo (this, bodyNode, item^.uid, formNode)
|
||||
form_ [onFormSubmit formSubmitHandler] $ do
|
||||
@ -1124,6 +1124,8 @@ renderItemNotes category item = cached (CacheItemNotes (item^.uid)) $ do
|
||||
JS.makeItemNotesEditor (
|
||||
this, JS.selectUid editingSectionUid,
|
||||
textareaUid,
|
||||
-- See Note [blurb diffing]
|
||||
markdownNull (item^.notes),
|
||||
contents,
|
||||
item^.uid) <>
|
||||
JS.switchSection (this, "editing" :: Text) <>
|
||||
|
@ -216,6 +216,8 @@ textarea.fullwidth {
|
||||
}
|
||||
|
||||
.diff-choices > * > .text {
|
||||
white-space: pre-wrap;
|
||||
font-family: monospace;
|
||||
border: 1px solid gray;
|
||||
padding: 5px 10px;
|
||||
margin: 5px 0px;
|
||||
|
Loading…
Reference in New Issue
Block a user