Added recent_changes module.

Revisited hooks management, and added new CMS_HOOK_MANAGER.
Added admin, and other link into navigation menu that goes into first sidebar.
Fixed theme info, and template for sidebar ids.
This commit is contained in:
2015-08-11 13:54:51 +02:00
parent 7cb4c0e9f4
commit b6adbfec33
28 changed files with 787 additions and 148 deletions

View File

@@ -97,8 +97,8 @@ feature -- Hooks
register_hooks (a_response: CMS_RESPONSE)
-- <Precursor>
do
a_response.subscribe_to_menu_system_alter_hook (Current)
a_response.subscribe_to_response_alter_hook (Current)
a_response.hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_response_alter_hook (Current)
end
response_alter (a_response: CMS_RESPONSE)
@@ -117,7 +117,7 @@ feature -- Hooks
-- TODO: we should probably use more side menu and less primary_menu.
create lnk.make ("Admin", "admin")
lnk.set_permission_arguments (<<"manage " + {CMS_ADMIN_MODULE}.name>>)
a_menu_system.primary_menu.extend (lnk)
a_menu_system.management_menu.extend (lnk)
end
end

View File

@@ -95,8 +95,8 @@ feature -- Hooks configuration
-- Module hooks configuration.
do
auto_subscribe_to_hooks (a_response)
a_response.subscribe_to_block_hook (Current)
a_response.subscribe_to_value_table_alter_hook (Current)
a_response.hooks.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_value_table_alter_hook (Current)
end
value_table_alter (a_value: CMS_VALUE_TABLE; a_response: CMS_RESPONSE)

View File

@@ -105,8 +105,8 @@ feature -- Hooks configuration
-- Module hooks configuration.
do
auto_subscribe_to_hooks (a_response)
a_response.subscribe_to_block_hook (Current)
a_response.subscribe_to_value_table_alter_hook (Current)
a_response.hooks.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_value_table_alter_hook (Current)
end
feature -- Hooks

View File

@@ -151,8 +151,8 @@ feature -- Hooks
register_hooks (a_response: CMS_RESPONSE)
do
a_response.subscribe_to_menu_system_alter_hook (Current)
a_response.subscribe_to_response_alter_hook (Current)
a_response.hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_response_alter_hook (Current)
end
response_alter (a_response: CMS_RESPONSE)

View File

@@ -247,17 +247,26 @@ feature -- Access: Node
debug ("refactor_fixme")
fixme ("Check preconditions")
end
Result := full_node (node_storage.node_by_id (a_id))
Result := safe_full_node (node_storage.node_by_id (a_id))
end
revision_node (a_node_id: INTEGER_64; a_revision_id: INTEGER_64): detachable CMS_NODE
do
Result := full_node (node_storage.node_by_id_and_revision (a_node_id, a_revision_id))
Result := safe_full_node (node_storage.node_by_id_and_revision (a_node_id, a_revision_id))
end
full_node (a_node: detachable CMS_NODE): detachable CMS_NODE
safe_full_node (a_node: detachable CMS_NODE): detachable CMS_NODE
do
if a_node /= Void then
Result := full_node (a_node)
end
end
full_node (a_node: CMS_NODE): CMS_NODE
-- If `a_node' is partial, return the full node from `a_node',
-- otherwise return directly `a_node'.
require
a_node_set: a_node /= Void
do
if attached {CMS_PARTIAL_NODE} a_node as l_partial_node then
if attached node_type_for (l_partial_node) as ct then

View File

@@ -23,6 +23,8 @@ inherit
CMS_HOOK_BLOCK
CMS_RECENT_CHANGES_HOOK
create
make
@@ -222,9 +224,12 @@ feature -- Hooks
register_hooks (a_response: CMS_RESPONSE)
-- <Precursor>
do
a_response.subscribe_to_menu_system_alter_hook (Current)
a_response.subscribe_to_block_hook (Current)
a_response.subscribe_to_response_alter_hook (Current)
a_response.hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_response_alter_hook (Current)
-- Module specific hook, if available.
a_response.hooks.subscribe_to_hook (Current, {CMS_RECENT_CHANGES_HOOK})
end
response_alter (a_response: CMS_RESPONSE)
@@ -253,13 +258,52 @@ feature -- Hooks
do
debug
create lnk.make ("List of nodes", "nodes")
a_menu_system.primary_menu.extend (lnk)
a_menu_system.navigation_menu.extend (lnk)
end
create lnk.make ("Trash", "trash")
a_menu_system.primary_menu.extend (lnk)
a_menu_system.navigation_menu.extend (lnk)
create lnk.make ("Create ..", "node")
a_menu_system.primary_menu.extend (lnk)
a_menu_system.navigation_menu.extend (lnk)
end
populate_recent_changes (a_changes: CMS_RECENT_CHANGE_CONTAINER; a_sources: LIST [READABLE_STRING_8])
local
params: CMS_DATA_QUERY_PARAMETERS
ch: CMS_RECENT_CHANGE_ITEM
n: CMS_NODE
l_info: STRING_8
do
create params.make (0, a_changes.limit)
if attached node_api as l_node_api then
across
l_node_api.content_types as ic
loop
a_sources.force (ic.item.name)
end
across l_node_api.recent_nodes (params) as ic loop
n := l_node_api.full_node (ic.item)
create ch.make (n.content_type, create {CMS_LOCAL_LINK}.make (n.title, "node/" + n.id.out), n.modification_date)
if n.creation_date ~ n.modification_date then
l_info := "new"
if not n.is_published then
l_info.append (" (unpublished)")
end
else
if n.is_trashed then
l_info := "trashed"
else
l_info := "updated"
if not n.is_published then
l_info.append (" (unpublished)")
end
end
end
ch.set_information (l_info)
ch.set_author (n.author)
a_changes.force (ch)
end
end
end
end

View File

@@ -274,7 +274,6 @@ feature {NONE} -- Trash:Restore
r: GENERIC_VIEW_CMS_RESPONSE
b: STRING
n: CMS_NODE
l_link: CMS_LOCAL_LINK
do
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
if

View File

@@ -13,6 +13,7 @@
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms" location="..\..\cms-safe.ecf"/>
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
<library name="cms_recent_changes_module" location="..\..\modules\recent_changes\recent_changes-safe.ecf" readonly="false"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="http_authorization" location="$ISE_LIBRARY\contrib\library\web\authentication\http_authorization\http_authorization-safe.ecf" readonly="false"/>

View File

@@ -192,8 +192,8 @@ feature -- Hooks configuration
-- Module hooks configuration.
do
auto_subscribe_to_hooks (a_response)
a_response.subscribe_to_block_hook (Current)
a_response.subscribe_to_value_table_alter_hook (Current)
a_response.hooks.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_value_table_alter_hook (Current)
end
feature -- Hooks

View File

@@ -170,8 +170,8 @@ feature -- Hooks configuration
-- Module hooks configuration.
do
auto_subscribe_to_hooks (a_response)
a_response.subscribe_to_block_hook (Current)
a_response.subscribe_to_value_table_alter_hook (Current)
a_response.hooks.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_value_table_alter_hook (Current)
end
feature -- Hooks

View File

@@ -0,0 +1,82 @@
note
description: "Container of recent change items, and associated parameters."
date: "$Date$"
revision: "$Revision$"
class
CMS_RECENT_CHANGE_CONTAINER
inherit
ITERABLE [CMS_RECENT_CHANGE_ITEM]
create
make
feature -- Initialization
make (a_limit: NATURAL_32; a_date: detachable DATE_TIME; a_source: detachable READABLE_STRING_8)
do
limit := a_limit
date := a_date
source := a_source
create items.make (a_limit.to_integer_32)
end
feature -- Settings
limit: NATURAL_32
date: detachable DATE_TIME
source: detachable READABLE_STRING_8
feature -- Access
items: ARRAYED_LIST [CMS_RECENT_CHANGE_ITEM]
-- List of recent events.
count: INTEGER
-- Number of change items.
do
Result := items.count
end
feature -- Access
new_cursor: ITERATION_CURSOR [CMS_RECENT_CHANGE_ITEM]
-- <Precursor>
do
Result := items.new_cursor
end
feature -- Change
force (a_item: CMS_RECENT_CHANGE_ITEM)
-- Add `a_item'.
do
items.force (a_item)
end
feature -- Sorting
sort
-- Sort `items' from older, to newer.
do
change_item_sorter.sort (items)
end
reverse_sort
-- Sort `items' from newer to older.
do
change_item_sorter.reverse_sort (items)
end
feature {NONE} -- Implementation
change_item_sorter: QUICK_SORTER [CMS_RECENT_CHANGE_ITEM]
-- New change item sorter.
once
create Result.make (create {COMPARABLE_COMPARATOR [CMS_RECENT_CHANGE_ITEM]})
end
end

View File

@@ -0,0 +1,64 @@
note
description: "Information related to change event."
date: "$Date$"
revision: "$Revision$"
class
CMS_RECENT_CHANGE_ITEM
inherit
COMPARABLE
create
make
feature {NONE} -- Initialization
make (a_source: READABLE_STRING_8; lnk: CMS_LOCAL_LINK; a_date_time: DATE_TIME)
do
source := a_source
link := lnk
date := a_date_time
end
feature -- Access
link: CMS_LOCAL_LINK
-- Local link associated with the resource.
date: DATE_TIME
-- Time of the event item.
author: detachable CMS_USER
-- Optional author.
source: READABLE_STRING_8
-- Source of Current event.
information: detachable READABLE_STRING_8
-- Optional information related to Current event.
--| For instance: creation, trashed, modified, ...
feature -- Element change
set_author (u: like author)
-- Set `author' to `u'.
do
author := u
end
set_information (a_info: like information)
-- Set `information' to `a_info'.
do
information := a_info
end
feature -- Comparison
is_less alias "<" (other: like Current): BOOLEAN
-- <Precursor>
do
Result := date < other.date
end
end

View File

@@ -0,0 +1,34 @@
note
description: "Hook provided by module {CMS_RECENT_CHANGES_MODULE}."
date: "$Date$"
revision: "$Revision$"
deferred class
CMS_RECENT_CHANGES_HOOK
inherit
CMS_HOOK
-- CMS_HOOK_WITH_WRAPPER
-- rename
-- wrapper as recent_changes_hook_wrapper
-- redefine
-- recent_changes_hook_wrapper
-- end
feature -- Invocation
populate_recent_changes (a_changes: CMS_RECENT_CHANGE_CONTAINER; a_sources: LIST [READABLE_STRING_8])
-- Populate recent changes inside `a_changes' according to associated parameters.
-- Also provide sources of information.
deferred
end
--feature -- Wrapper
-- recent_changes_hook_wrapper: detachable CMS_RECENT_CHANGES_HOOK_WRAPPER
-- do
-- create Result.make (Current)
-- end
end

View File

@@ -0,0 +1,180 @@
note
description: "CMS module that bring support for recent changes."
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
revision: "$Revision: 96616 $"
class
CMS_RECENT_CHANGES_MODULE
inherit
CMS_MODULE
rename
module_api as recent_changes_api
redefine
register_hooks
end
CMS_HOOK_MENU_SYSTEM_ALTER
CMS_HOOK_RESPONSE_ALTER
create
make
feature {NONE} -- Initialization
make
-- Create Current module, disabled by default.
do
version := "1.0"
description := "Service to access recent changes"
package := "notification"
end
feature -- Access
name: STRING = "recent_changes"
feature -- Access: router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- <Precursor>
do
a_router.handle ("/recent_changes/", create {WSF_URI_AGENT_HANDLER}.make (agent handle_recent_changes (a_api, ?, ?)), a_router.methods_head_get)
end
feature -- Handler
handle_recent_changes (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
l_changes: CMS_RECENT_CHANGE_CONTAINER
l_sources: ARRAYED_LIST [READABLE_STRING_8]
dt, prev_dt: detachable DATE
ch: CMS_RECENT_CHANGE_ITEM
htdate: HTTP_DATE
l_content: STRING
l_form: CMS_FORM
l_select: WSF_FORM_SELECT
do
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
create l_changes.make (25, Void, Void)
create l_content.make (1024)
if attached r.hooks.subscribers ({CMS_RECENT_CHANGES_HOOK}) as lst then
create l_sources.make (lst.count)
across
lst as ic
loop
if attached {CMS_RECENT_CHANGES_HOOK} ic.item as h then
h.populate_recent_changes (l_changes, l_sources)
end
end
create l_form.make (req.percent_encoded_path_info, "recent-changes")
create l_select.make ("source")
l_select.set_label ("Sources")
across
l_sources as ic
loop
l_select.add_option (create {WSF_FORM_SELECT_OPTION}.make (ic.item, ic.item))
end
l_form.extend (l_select)
l_form.extend_html_text ("<br/>")
l_form.append_to_html (create {CMS_TO_WSF_THEME}.make (r, r.theme), l_content)
end
l_changes.reverse_sort
l_content.append ("<table class=%"recent-changes%" style=%"border-spacing: 5px;%">")
l_content.append ("<thead>")
l_content.append ("<tr>")
l_content.append ("<th>Date</th>")
l_content.append ("<th>Source</th>")
l_content.append ("<th>Resource</th>")
l_content.append ("<th>User</th>")
l_content.append ("<th>Information</th>")
l_content.append ("</tr>")
l_content.append ("</thead>")
l_content.append ("<tbody>")
across
l_changes as ic
loop
ch := ic.item
dt := ch.date.date
if dt /~ prev_dt then
l_content.append ("<tr>")
l_content.append ("<td class=%"title%" colspan=%"5%">")
l_content.append (dt.formatted_out ("ddd, dd mmm yyyy"))
l_content.append ("</td>")
l_content.append ("</tr>")
end
prev_dt := dt
l_content.append ("<tr>")
l_content.append ("<td class=%"date%">")
create htdate.make_from_date_time (ch.date)
htdate.append_to_rfc1123_string (l_content)
l_content.append ("</td>")
l_content.append ("<td class=%"source%">" + ch.source + "</td>")
l_content.append ("<td class=%"resource%">")
l_content.append (r.link (ch.link.title, ch.link.location, Void))
l_content.append ("</td>")
l_content.append ("<td class=%"user%">")
if attached ch.author as u then
l_content.append (r.link (u.name, "user/" + u.id.out, Void))
end
l_content.append ("</td>")
l_content.append ("<td class=%"info%">")
if attached ch.information as l_info then
l_content.append ("<strong>" + l_info + "</strong> ")
end
l_content.append ("</td>")
l_content.append ("</tr>%N")
end
l_content.append ("</tbody>")
l_content.append ("</table>%N")
r.set_main_content (l_content)
r.set_title ("Last " + l_changes.count.out + " changes")
r.execute
end
feature -- Hooks configuration
register_hooks (a_response: CMS_RESPONSE)
-- Module hooks configuration.
do
a_response.hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_response_alter_hook (Current)
end
feature -- Hook
response_alter (a_response: CMS_RESPONSE)
do
a_response.add_additional_head_line ("[
<style>
table.recent-changes th { padding: 3px; }
table.recent-changes td { padding: 3px; border: dotted 1px #ddd; }
table.recent-changes td.date { padding-left: 15px; }
table.recent-changes td.title { font-weight: bold; }
</style>
]", True)
end
menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
-- Hook execution on collection of menu contained by `a_menu_system'
-- for related response `a_response'.
local
lnk: CMS_LOCAL_LINK
do
create lnk.make ("Recent changes", "recent_changes/")
lnk.set_permission_arguments (<<"view recent changes">>)
a_menu_system.navigation_menu.extend (lnk)
end
-- populate_recent_changes (lst: LIST [CMS_RECENT_CHANGE_ITEM]; a_date: detachable DATE_TIME; a_limit: INTEGER)
-- do
-- end
end

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="recent_changes" uuid="1C3893A3-46FC-4E60-86AE-37CB7939BC7F" library_target="recent_changes">
<target name="recent_changes">
<root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="cms" location="..\..\cms-safe.ecf"/>
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf" readonly="false"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>