Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
private_message
Manage
Activity
Members
Labels
Plan
Wiki
Custom issue tracker
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Model registry
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
project
private_message
Merge requests
!166
Refactor inbox_block_script library.
Code
Review changes
Check out branch
Download
Patches
Plain diff
Merged
Refactor inbox_block_script library.
issue/private_message-3491252:3491252-refactor-inboxblockscript-library
into
4.x
Overview
0
Commits
24
Pipelines
12
Changes
10
Merged
Adrian Lorenc
requested to merge
issue/private_message-3491252:3491252-refactor-inboxblockscript-library
into
4.x
3 months ago
Overview
0
Commits
24
Pipelines
12
Changes
3
Expand
Closes
#3491252
0
0
Merge request reports
Compare
version 10
version 11
a66d4b43
3 months ago
version 10
197a117a
3 months ago
version 9
8ce5db89
3 months ago
version 8
a9e45f16
3 months ago
version 7
fa6afe03
3 months ago
version 6
98b0723c
3 months ago
version 5
391cfd18
3 months ago
version 4
f734a4f8
3 months ago
version 3
e5056d75
3 months ago
version 2
9c04c8cc
3 months ago
version 1
cd0d5bd6
3 months ago
4.x (base)
and
version 11
latest version
a66d4b43
24 commits,
3 months ago
version 11
a66d4b43
24 commits,
3 months ago
version 10
197a117a
18 commits,
3 months ago
version 9
8ce5db89
17 commits,
3 months ago
version 8
a9e45f16
16 commits,
3 months ago
version 7
fa6afe03
15 commits,
3 months ago
version 6
98b0723c
14 commits,
3 months ago
version 5
391cfd18
13 commits,
3 months ago
version 4
f734a4f8
12 commits,
3 months ago
version 3
e5056d75
11 commits,
3 months ago
version 2
9c04c8cc
2 commits,
3 months ago
version 1
cd0d5bd6
1 commit,
3 months ago
Show latest version
3 files
+
35
−
22
Inline
Compare changes
Side-by-side
Inline
Show whitespace changes
Show one file at a time
Files
3
Search (e.g. *.vue) (Ctrl+P)
js/private_message_inbox_block.js
+
207
−
225
Options
@@ -3,271 +3,253 @@
* Adds JavaScript functionality to the private message inbox block.
*/
Drupal
.
PrivateMessageInbox
=
{};
Drupal
.
PrivateMessageInbox
.
updateInbox
=
{};
((
$
,
Drupal
,
drupalSettings
,
window
,
once
)
=>
{
let
container
;
let
updateInterval
;
let
loadingPrev
;
let
loadingNew
;
((
Drupal
,
drupalSettings
,
window
,
once
)
=>
{
/**
* Used to manually trigger Drupal's JavaScript commands.
* @param {Object} data The data.
* Private message inbox block functionality.
*/
function
triggerCommands
(
data
)
{
const
ajaxObject
=
Drupal
.
ajax
(
{
url
:
''
,
base
:
false
,
element
:
false
,
progress
:
false
,
}
);
class
PrivateMessageInboxBlock
{
const
ructor
()
{
this
.
container
=
null
;
this
.
loadingPrevInProgress
=
false
;
this
.
loadingNewInProgress
=
false
;
this
.
updateTimeoutId
=
null
;
}
// Trigger any ajax commands in the response.
ajaxObject
.
success
(
data
,
'
success
'
);
}
/**
* Initialize the block with default state and handlers.
*
* @param {HTMLElement} blockWrapper
* The inbox block.
*/
init
(
blockWrapper
)
{
this
.
container
=
blockWrapper
;
const
threadId
=
this
.
container
.
querySelector
(
'
.private-message-thread
'
)
?.
dataset
.
threadId
;
if
(
threadId
)
{
Drupal
.
PrivateMessageUtils
.
setActiveThread
(
threadId
);
}
this
.
attachLoadOldButton
();
this
.
scheduleInboxUpdate
();
}
/**
* Updates the inbox after an Ajax call.
*/
function
updateInbox
()
{
if
(
!
loadingNew
)
{
loadingNew
=
true
;
/**
* Updates the inbox with new threads.
*/
updateInbox
()
{
if
(
this
.
loadingNewInProgress
)
{
return
;
}
this
.
loadingNewInProgress
=
true
;
const
ids
=
{};
if
(
container
.
length
>
0
)
{
container
[
0
]
.
querySelectorAll
(
'
.private-message-thread-inbox
'
)
.
forEach
((
el
)
=>
{
ids
[
el
.
dataset
.
threadId
]
=
el
.
dataset
.
lastUpdate
;
});
}
this
.
container
.
querySelectorAll
(
'
.private-message-thread-inbox
'
)
.
forEach
((
el
)
=>
{
ids
[
el
.
dataset
.
threadId
]
=
el
.
dataset
.
lastUpdate
;
});
$
.
ajax
({
Drupal
.
ajax
({
url
:
drupalSettings
.
privateMessageInboxBlock
.
loadNewUrl
,
method
:
'
POST
'
,
data
:
{
ids
},
success
(
data
)
{
loadingNew
=
false
;
triggerCommands
(
data
);
if
(
updateInterval
)
{
window
.
setTimeout
(
updateInbox
,
updateInterval
);
}
},
});
submit
:
{
ids
},
})
.
execute
()
.
always
(()
=>
{
this
.
loadingNewInProgress
=
false
;
this
.
scheduleInboxUpdate
();
});
}
}
/**
* Reorders the inbox after an Ajax Load, to show newest threads first.
* @param {Array} threadIds The threads IDs.
* @param {Array} newThreads The new Threads.
*/
function
reorderInbox
(
threadIds
,
newThreads
)
{
const
map
=
{};
container
[
0
]
.
querySelectorAll
(
'
:scope > .private-message-thread-inbox
'
)
.
forEach
((
el
)
=>
{
map
[
el
.
dataset
.
threadId
]
=
$
(
el
);
});
threadIds
.
forEach
((
threadId
)
=>
{
if
(
newThreads
[
threadId
])
{
if
(
map
[
threadId
])
{
map
[
threadId
].
remove
();
}
$
(
'
<div/>
'
).
html
(
newThreads
[
threadId
]).
contents
().
appendTo
(
container
);
}
else
if
(
map
[
threadId
])
{
container
.
append
(
map
[
threadId
]);
/**
* Sets a timeout for inbox updates.
*/
scheduleInboxUpdate
()
{
if
(
this
.
updateTimeoutId
)
{
window
.
clearTimeout
(
this
.
updateTimeoutId
);
}
});
Drupal
.
attachBehaviors
(
container
[
0
]);
}
const
interval
=
drupalSettings
.
privateMessageInboxBlock
.
ajaxRefreshRate
*
1000
;
if
(
interval
)
{
this
.
updateTimeoutId
=
window
.
setTimeout
(
()
=>
this
.
updateInbox
(),
interval
,
);
}
}
/**
* Inserts older threads into the inbox after an Ajax load.
* @param {string} threads The threads HTML.
*/
function
insertPreviousThreads
(
threads
)
{
const
contents
=
$
(
'
<div/>
'
).
html
(
threads
).
contents
();
/**
* Appends older threads to the inbox.
*
* @param {string} threadsHtml
* HTML content of threads.
*/
insertPreviousThreads
(
threadsHtml
)
{
const
newNodes
=
Drupal
.
PrivateMessageUtils
.
parseHTML
(
threadsHtml
);
contents
.
css
(
'
display
'
,
'
none
'
).
appendTo
(
container
).
slideDown
(
300
);
Drupal
.
attachBehaviors
(
contents
[
0
]);
}
Array
.
from
(
newNodes
).
forEach
((
node
)
=>
{
const
appendedElement
=
this
.
container
.
appendChild
(
node
);
/**
* Adds CSS classes to the currently selected thread.
* @param {string} threadId The thread id.
*/
function
setActiveThread
(
threadId
)
{
container
.
find
(
'
.active-thread:first
'
).
removeClass
(
'
active-thread
'
);
container
.
find
(
`.private-message-thread[data-thread-id="
${
threadId
}
"]:first`
)
.
removeClass
(
'
unread-thread
'
)
.
addClass
(
'
active-thread
'
);
}
Drupal
.
attachBehaviors
(
appendedElement
);
Drupal
.
PrivateMessageSlide
.
toggleSlide
(
appendedElement
,
true
);
});
}
/**
* Click handler for the button that loads older threads into the inbox.
* @param {Object} e The event.
*/
function
loadOldThreadWatcherHandler
(
e
)
{
e
.
preventDefault
();
/**
* Handles loading older threads.
*
* @param {Event} e
* The click event.
*/
loadOldThreads
(
e
)
{
e
.
preventDefault
();
if
(
this
.
loadingPrevInProgress
)
{
return
;
}
if
(
!
loadingPrev
)
{
loadingPrev
=
true
;
this
.
loadingPrevInProgress
=
true
;
let
oldestTimestamp
;
container
[
0
].
querySelectorAll
(
'
.private-message-thread
'
).
forEach
((
el
)
=>
{
const
timestamp
=
parseInt
(
el
.
dataset
.
lastUpdate
,
10
);
oldestTimestamp
=
!
oldestTimestamp
?
timestamp
:
Math
.
min
(
timestamp
,
oldestTimestamp
);
});
const
oldestTimestamp
=
Array
.
from
(
this
.
container
.
querySelectorAll
(
'
.private-message-thread
'
),
).
reduce
((
minTime
,
el
)
=>
{
return
Math
.
min
(
minTime
,
parseInt
(
el
.
dataset
.
lastUpdate
,
10
));
},
Infinity
);
$
.
ajax
({
Drupal
.
ajax
({
url
:
drupalSettings
.
privateMessageInboxBlock
.
loadPrevUrl
,
data
:
{
submit
:
{
timestamp
:
oldestTimestamp
,
count
:
drupalSettings
.
privateMessageInboxBlock
.
threadCount
,
},
success
(
data
)
{
loadingPrev
=
false
;
triggerCommands
(
data
);
},
});
})
.
execute
()
.
always
(()
=>
{
this
.
loadingPrevInProgress
=
false
;
});
}
}
/**
* Watches the button that loads previous threads into the inbox.
* @param {Object} context The context.
*/
function
loadOlderThreadWatcher
(
context
)
{
once
(
'
load-older-threads-watcher
'
,
'
#load-previous-threads-button
'
,
context
,
).
forEach
((
el
)
=>
{
el
.
addEventListener
(
'
click
'
,
loadOldThreadWatcherHandler
);
});
}
/**
* Click Handler executed when private message threads are clicked.
*
* Loads the thread into the private message window.
* @param {Event} e The event.
*/
const
inboxThreadLinkListenerHandler
=
(
e
)
=>
{
if
(
Drupal
.
PrivateMessages
)
{
e
.
preventDefault
();
const
threadId
=
e
.
currentTarget
.
dataset
.
threadId
;
Drupal
.
PrivateMessages
.
loadThread
(
threadId
);
setActiveThread
(
threadId
);
/**
* Reorders the inbox to show the newest threads first.
*
* @param {Array} threadIds
* Thread IDs in the desired order.
* @param {Array} newThreads
* HTML content of new threads keyed by thread ID.
*/
reorderInbox
(
threadIds
,
newThreads
)
{
const
existingThreads
=
{};
this
.
container
.
querySelectorAll
(
'
:scope > .private-message-thread-inbox
'
)
.
forEach
((
el
)
=>
{
existingThreads
[
el
.
dataset
.
threadId
]
=
el
;
});
threadIds
.
forEach
((
threadId
)
=>
{
if
(
newThreads
[
threadId
])
{
if
(
existingThreads
[
threadId
])
{
existingThreads
[
threadId
].
remove
();
}
const
newThreadContent
=
Drupal
.
PrivateMessageUtils
.
parseHTML
(
newThreads
[
threadId
],
);
Array
.
from
(
newThreadContent
).
forEach
((
child
)
=>
{
const
appendedElement
=
this
.
container
.
appendChild
(
child
);
Drupal
.
attachBehaviors
(
appendedElement
);
});
}
else
if
(
existingThreads
[
threadId
])
{
const
appendedElement
=
this
.
container
.
appendChild
(
existingThreads
[
threadId
],
);
Drupal
.
attachBehaviors
(
appendedElement
);
}
});
}
};
/**
* Watches private message threads for clicks, so new threads can be loaded.
* @param {Object} context The context.
*/
function
inboxThreadLinkListener
(
context
)
{
once
(
'
inbox-thread-link-listener
'
,
'
.private-message-inbox-thread-link
'
,
context
,
).
forEach
((
el
)
=>
{
el
.
addEventListener
(
'
click
'
,
inboxThreadLinkListenerHandler
);
});
}
/**
* Initializes the private message inbox JavaScript.
*/
function
init
(
context
)
{
$
(
once
(
'
init-inbox-block
'
,
'
.block-private-message-inbox-block .private-message-thread--full-container
'
,
context
,
),
).
each
(
function
()
{
container
=
$
(
this
);
const
threadId
=
container
.
children
(
'
.private-message-thread:first
'
)
.
attr
(
'
data-thread-id
'
);
setActiveThread
(
threadId
);
/**
* Attaches the "Load Older Threads" button handler.
*/
attachLoadOldButton
()
{
if
(
drupalSettings
.
privateMessageInboxBlock
.
totalThreads
>
drupalSettings
.
privateMessageInboxBlock
.
itemsToShow
)
{
$
(
'
<div/>
'
,
{
id
:
'
load-previous-threads-button-wrapper
'
})
.
append
(
$
(
'
<a/>
'
,
{
href
:
'
#
'
,
id
:
'
load-previous-threads-button
'
}).
text
(
Drupal
.
t
(
'
Load Previous
'
),
),
)
.
insertAfter
(
container
);
loadOlderThreadWatcher
(
document
);
}
updateInterval
=
drupalSettings
.
privateMessageInboxBlock
.
ajaxRefreshRate
*
1000
;
if
(
updateInterval
)
{
window
.
setTimeout
(
updateInbox
,
updateInterval
);
Drupal
.
privateMessageInboxPrevious
.
displayButton
(
this
.
container
,
(
e
)
=>
this
.
loadOldThreads
(
e
),
);
}
}
);
}
}
const
privateMessageInboxBlock
=
new
PrivateMessageInboxBlock
();
/**
* Attaches the private message inbox block behavior.
*/
Drupal
.
behaviors
.
privateMessageInboxBlock
=
{
attach
(
context
)
{
init
(
context
);
inboxThreadLinkListener
(
context
);
Drupal
.
AjaxCommands
.
prototype
.
insertInboxOldPrivateMessageThreads
=
(
ajax
,
response
,
)
=>
{
if
(
response
.
threads
)
{
insertPreviousThreads
(
response
.
threads
);
}
if
(
!
response
.
threads
||
!
response
.
hasNext
)
{
$
(
'
#load-previous-threads-button
'
)
.
parent
()
.
slideUp
(
300
,
function
()
{
$
(
this
).
remove
();
});
}
};
Drupal
.
AjaxCommands
.
prototype
.
privateMessageInboxUpdate
=
(
ajax
,
response
,
)
=>
reorderInbox
(
response
.
threadIds
,
response
.
newThreads
);
Drupal
.
AjaxCommands
.
prototype
.
privateMessageTriggerInboxUpdate
=
()
=>
updateInbox
();
const
containerFormContext
=
once
(
'
private-message-inbox-block
'
,
'
.block-private-message-inbox-block .private-message-thread--full-container
'
,
context
,
).
shift
();
if
(
Drupal
.
PrivateMessages
)
{
Drupal
.
PrivateMessages
.
setActiveThread
=
(
id
)
=>
setActiveThread
(
id
)
;
if
(
!
containerFormContext
)
{
return
;
}
Drupal
.
P
rivateMessageInbox
.
updateInbox
=
()
=>
updateInbox
(
);
p
rivateMessageInbox
Block
.
init
(
containerFormContext
);
},
detach
(
context
)
{
$
(
context
)
.
find
(
'
#load-previous-threads-button
'
)
.
unbind
(
'
click
'
,
loadOldThreadWatcherHandler
);
$
(
context
)
.
find
(
'
.private-message-inbox-thread-link
'
)
.
unbind
(
'
click
'
,
inboxThreadLinkListenerHandler
);
Drupal
.
privateMessageInboxPrevious
.
detachEventListener
(
context
,
privateMessageInboxBlock
.
loadOldThreads
.
bind
(
privateMessageInboxBlock
),
);
},
};
})(
jQuery
,
Drupal
,
drupalSettings
,
window
,
once
);
/**
* Custom AJAX commands for private message inbox.
*
* @param {Drupal.Ajax} ajax
* The Drupal Ajax object.
* @param {object} response
* Object holding the server response.
*/
Drupal
.
AjaxCommands
.
prototype
.
insertInboxOldPrivateMessageThreads
=
(
ajax
,
response
,
)
=>
{
if
(
response
.
threads
)
{
privateMessageInboxBlock
.
insertPreviousThreads
(
response
.
threads
);
}
if
(
!
response
.
threads
||
!
response
.
hasNext
)
{
Drupal
.
privateMessageInboxPrevious
.
slideDownButton
();
}
};
/**
* Custom AJAX command to update the inbox with new threads.
*
* @param {Drupal.Ajax} ajax
* The Drupal Ajax object.
* @param {object} response
* Object holding the server response.
*/
Drupal
.
AjaxCommands
.
prototype
.
privateMessageInboxUpdate
=
(
ajax
,
response
,
)
=>
{
privateMessageInboxBlock
.
reorderInbox
(
response
.
threadIds
,
response
.
newThreads
,
);
};
/**
* Custom AJAX command to trigger an inbox update.
*/
Drupal
.
AjaxCommands
.
prototype
.
privateMessageTriggerInboxUpdate
=
()
=>
{
privateMessageInboxBlock
.
updateInbox
();
};
})(
Drupal
,
drupalSettings
,
window
,
once
);
Loading