Added blog module as example, this is far from being a real blog module.

but this is an example about on to add a new content type, and support it.
Fixed new node form workflow.

The current state is not final, it requires many changes, but for now, it implements a node editing workflow.
This commit is contained in:
2015-04-15 22:32:38 +02:00
parent f2bb061488
commit a56338ad17
21 changed files with 1040 additions and 226 deletions

View File

@@ -45,7 +45,7 @@ feature {NONE} -- Implementation
add_content_type_webform_manager (create {CMS_PAGE_CONTENT_TYPE_WEBFORM_MANAGER}.make (ct))
end
feature {NODE_MODULE} -- Access nodes storage.
feature {CMS_MODULE} -- Access nodes storage.
node_storage: CMS_NODE_STORAGE_I
@@ -104,7 +104,7 @@ feature -- URL
-- or URI of path for selection of new content possibilities if ct is Void.
do
if ct /= Void then
Result := "/node/new/" + ct.name
Result := "/node/add/" + ct.name
else
Result := "/node/new"
end

View File

@@ -31,7 +31,7 @@ feature {CMS_CONTENT_TYPE} -- Conversion
do
Precursor (a_node)
if attached {CMS_PAGE} a_node as l_page then
set_parent (l_page)
set_parent (l_page.parent)
end
end

View File

@@ -36,8 +36,8 @@ feature -- Forms ...
end
change_node (response: NODE_RESPONSE; a_form_data: WSF_FORM_DATA; a_node: CMS_NODE)
require
a_node.has_id
-- require
-- a_node.has_id
deferred
end

View File

@@ -0,0 +1,159 @@
note
description: "Summary description for {CMS_NODE_CONTENT_TYPE_WEBFORM_MANAGER}."
date: "$Date$"
revision: "$Revision$"
class
CMS_NODE_CONTENT_TYPE_WEBFORM_MANAGER [G -> CMS_NODE]
inherit
CMS_CONTENT_TYPE_WEBFORM_MANAGER
redefine
content_type
end
create
make
feature -- Access
content_type: CMS_CONTENT_TYPE
-- Associated content type.
feature -- Forms ...
fill_edit_form (response: NODE_RESPONSE; f: CMS_FORM; a_node: detachable like new_node)
local
ti: WSF_FORM_TEXT_INPUT
fset: WSF_FORM_FIELD_SET
ta: WSF_FORM_TEXTAREA
tselect: WSF_FORM_SELECT
opt: WSF_FORM_SELECT_OPTION
do
create ti.make ("title")
ti.set_label ("Title")
ti.set_size (70)
if a_node /= Void then
ti.set_text_value (a_node.title)
end
ti.set_is_required (True)
f.extend (ti)
f.extend_html_text ("<br/>")
create ta.make ("body")
ta.set_rows (10)
ta.set_cols (70)
if a_node /= Void then
ta.set_text_value (a_node.content)
end
-- ta.set_label ("Body")
ta.set_description ("This is the main content")
ta.set_is_required (False)
create fset.make
fset.set_legend ("Body")
fset.extend (ta)
fset.extend_html_text ("<br/>")
create tselect.make ("format")
tselect.set_label ("Body's format")
tselect.set_is_required (True)
across
content_type.available_formats as c
loop
create opt.make (c.item.name, c.item.title)
if attached c.item.html_help as f_help then
opt.set_description ("<ul>" + f_help + "</ul>")
end
tselect.add_option (opt)
end
if a_node /= Void and then attached a_node.format as l_format then
tselect.set_text_by_value (l_format)
end
fset.extend (tselect)
f.extend (fset)
end
change_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: like new_node)
local
b: detachable READABLE_STRING_8
f: detachable CONTENT_FORMAT
do
if attached fd.integer_item ("id") as l_id and then l_id > 0 then
check a_node.id = l_id end
end
if attached fd.string_item ("title") as l_title then
a_node.set_title (l_title)
end
if attached fd.string_item ("body") as l_body then
b := l_body
end
if attached fd.string_item ("format") as s_format and then attached response.api.format (s_format) as f_format then
f := f_format
elseif a_node /= Void and then attached a_node.format as s_format and then attached response.api.format (s_format) as f_format then
f := f_format
else
f := response.api.formats.default_format
end
if b /= Void then
a_node.set_content (b, Void, f.name) -- FIXME: summary
end
end
new_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: detachable like new_node): like content_type.new_node
-- <Precursor>
local
b: detachable READABLE_STRING_8
f: detachable CONTENT_FORMAT
l_node: detachable like new_node
do
l_node := a_node
if attached fd.integer_item ("id") as l_id and then l_id > 0 then
if l_node /= Void then
check l_node.id = l_id end
else
if attached {like new_node} response.node_api.node (l_id) as n then
l_node := n
else
-- FIXME: Error
end
end
end
if attached fd.string_item ("title") as l_title then
if l_node = Void then
l_node := content_type.new_node (Void)
l_node.set_title (l_title)
else
l_node.set_title (l_title)
end
else
if l_node = Void then
l_node := content_type.new_node_with_title ("...", Void)
end
end
l_node.set_author (response.user)
if attached fd.string_item ("body") as l_body then
b := l_body
end
if attached fd.string_item ("format") as s_format and then attached response.api.format (s_format) as f_format then
f := f_format
elseif a_node /= Void and then attached a_node.format as s_format and then attached response.api.format (s_format) as f_format then
f := f_format
else
f := response.api.formats.default_format
end
if b /= Void then
l_node.set_content (b, Void, f.name)
end
Result := l_node
end
end

View File

@@ -8,7 +8,7 @@ class
CMS_PAGE_CONTENT_TYPE_WEBFORM_MANAGER
inherit
CMS_CONTENT_TYPE_WEBFORM_MANAGER
CMS_NODE_CONTENT_TYPE_WEBFORM_MANAGER [CMS_PAGE]
redefine
content_type
end
@@ -23,138 +23,138 @@ feature -- Access
feature -- Forms ...
fill_edit_form (response: NODE_RESPONSE; f: CMS_FORM; a_node: detachable CMS_NODE)
local
ti: WSF_FORM_TEXT_INPUT
fset: WSF_FORM_FIELD_SET
ta: WSF_FORM_TEXTAREA
tselect: WSF_FORM_SELECT
opt: WSF_FORM_SELECT_OPTION
do
create ti.make ("title")
ti.set_label ("Title")
ti.set_size (70)
if a_node /= Void then
ti.set_text_value (a_node.title)
end
ti.set_is_required (True)
f.extend (ti)
-- fill_edit_form (response: NODE_RESPONSE; f: CMS_FORM; a_node: detachable CMS_NODE)
-- local
-- ti: WSF_FORM_TEXT_INPUT
-- fset: WSF_FORM_FIELD_SET
-- ta: WSF_FORM_TEXTAREA
-- tselect: WSF_FORM_SELECT
-- opt: WSF_FORM_SELECT_OPTION
-- do
-- create ti.make ("title")
-- ti.set_label ("Title")
-- ti.set_size (70)
-- if a_node /= Void then
-- ti.set_text_value (a_node.title)
-- end
-- ti.set_is_required (True)
-- f.extend (ti)
f.extend_html_text ("<br/>")
-- f.extend_html_text ("<br/>")
create ta.make ("body")
ta.set_rows (10)
ta.set_cols (70)
if a_node /= Void then
ta.set_text_value (a_node.content)
end
-- ta.set_label ("Body")
ta.set_description ("This is the main content")
ta.set_is_required (False)
-- create ta.make ("body")
-- ta.set_rows (10)
-- ta.set_cols (70)
-- if a_node /= Void then
-- ta.set_text_value (a_node.content)
-- end
---- ta.set_label ("Body")
-- ta.set_description ("This is the main content")
-- ta.set_is_required (False)
create fset.make
fset.set_legend ("Body")
fset.extend (ta)
-- create fset.make
-- fset.set_legend ("Body")
-- fset.extend (ta)
fset.extend_html_text ("<br/>")
-- fset.extend_html_text ("<br/>")
create tselect.make ("format")
tselect.set_label ("Body's format")
tselect.set_is_required (True)
across
content_type.available_formats as c
loop
create opt.make (c.item.name, c.item.title)
if attached c.item.html_help as f_help then
opt.set_description ("<ul>" + f_help + "</ul>")
end
tselect.add_option (opt)
end
if a_node /= Void and then attached a_node.format as l_format then
tselect.set_text_by_value (l_format)
end
-- create tselect.make ("format")
-- tselect.set_label ("Body's format")
-- tselect.set_is_required (True)
-- across
-- content_type.available_formats as c
-- loop
-- create opt.make (c.item.name, c.item.title)
-- if attached c.item.html_help as f_help then
-- opt.set_description ("<ul>" + f_help + "</ul>")
-- end
-- tselect.add_option (opt)
-- end
-- if a_node /= Void and then attached a_node.format as l_format then
-- tselect.set_text_by_value (l_format)
-- end
fset.extend (tselect)
-- fset.extend (tselect)
f.extend (fset)
-- f.extend (fset)
end
-- end
change_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: like new_node)
local
b: detachable READABLE_STRING_8
f: detachable CONTENT_FORMAT
do
if attached fd.integer_item ("id") as l_id and then l_id > 0 then
check a_node.id = l_id end
end
if attached fd.string_item ("title") as l_title then
a_node.set_title (l_title)
end
-- change_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: like new_node)
-- local
-- b: detachable READABLE_STRING_8
-- f: detachable CONTENT_FORMAT
-- do
-- if attached fd.integer_item ("id") as l_id and then l_id > 0 then
-- check a_node.id = l_id end
-- end
-- if attached fd.string_item ("title") as l_title then
-- a_node.set_title (l_title)
-- end
if attached fd.string_item ("body") as l_body then
b := l_body
end
if attached fd.string_item ("format") as s_format and then attached response.api.format (s_format) as f_format then
f := f_format
elseif a_node /= Void and then attached a_node.format as s_format and then attached response.api.format (s_format) as f_format then
f := f_format
else
f := response.api.formats.default_format
end
if b /= Void then
a_node.set_content (b, Void, f.name) -- FIXME: summary
end
end
-- if attached fd.string_item ("body") as l_body then
-- b := l_body
-- end
-- if attached fd.string_item ("format") as s_format and then attached response.api.format (s_format) as f_format then
-- f := f_format
-- elseif a_node /= Void and then attached a_node.format as s_format and then attached response.api.format (s_format) as f_format then
-- f := f_format
-- else
-- f := response.api.formats.default_format
-- end
-- if b /= Void then
-- a_node.set_content (b, Void, f.name) -- FIXME: summary
-- end
-- end
new_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: detachable like new_node): CMS_PAGE
-- <Precursor>
local
b: detachable READABLE_STRING_8
f: detachable CONTENT_FORMAT
l_node: detachable like new_node
do
l_node := a_node
if attached fd.integer_item ("id") as l_id and then l_id > 0 then
if l_node /= Void then
check l_node.id = l_id end
else
if attached {like new_node} response.node_api.node (l_id) as n then
l_node := n
else
-- FIXME: Error
end
end
end
if attached fd.string_item ("title") as l_title then
if l_node = Void then
l_node := content_type.new_node (Void)
l_node.set_title (l_title)
else
l_node.set_title (l_title)
end
else
if l_node = Void then
l_node := content_type.new_node_with_title ("...", Void)
end
end
l_node.set_author (response.user)
-- new_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: detachable like new_node): CMS_PAGE
-- -- <Precursor>
-- local
-- b: detachable READABLE_STRING_8
-- f: detachable CONTENT_FORMAT
-- l_node: detachable like new_node
-- do
-- l_node := a_node
-- if attached fd.integer_item ("id") as l_id and then l_id > 0 then
-- if l_node /= Void then
-- check l_node.id = l_id end
-- else
-- if attached {like new_node} response.node_api.node (l_id) as n then
-- l_node := n
-- else
-- -- FIXME: Error
-- end
-- end
-- end
-- if attached fd.string_item ("title") as l_title then
-- if l_node = Void then
-- l_node := content_type.new_node (Void)
-- l_node.set_title (l_title)
-- else
-- l_node.set_title (l_title)
-- end
-- else
-- if l_node = Void then
-- l_node := content_type.new_node_with_title ("...", Void)
-- end
-- end
-- l_node.set_author (response.user)
if attached fd.string_item ("body") as l_body then
b := l_body
end
if attached fd.string_item ("format") as s_format and then attached response.api.format (s_format) as f_format then
f := f_format
elseif a_node /= Void and then attached a_node.format as s_format and then attached response.api.format (s_format) as f_format then
f := f_format
else
f := response.api.formats.default_format
end
if b /= Void then
l_node.set_content (b, Void, f.name)
end
Result := l_node
end
-- if attached fd.string_item ("body") as l_body then
-- b := l_body
-- end
-- if attached fd.string_item ("format") as s_format and then attached response.api.format (s_format) as f_format then
-- f := f_format
-- elseif a_node /= Void and then attached a_node.format as s_format and then attached response.api.format (s_format) as f_format then
-- f := f_format
-- else
-- f := response.api.formats.default_format
-- end
-- if b /= Void then
-- l_node.set_content (b, Void, f.name)
-- end
-- Result := l_node
-- end
end

View File

@@ -59,6 +59,41 @@ feature -- Execution
fd := f.last_data
end
if attached redirection as l_location then
-- FIXME: Hack for now
set_title (l_node.title)
add_to_menu (create {CMS_LOCAL_LINK}.make ("View", node_url (l_node)), primary_tabs)
add_to_menu (create {CMS_LOCAL_LINK}.make ("Edit", "/node/" + l_node.id.out + "/edit"), primary_tabs)
b.append ("saved")
else
set_title ("Edit #" + l_node.id.out)
add_to_menu (create {CMS_LOCAL_LINK}.make ("View", node_url (l_node)), primary_tabs)
add_to_menu (create {CMS_LOCAL_LINK}.make ("Edit", "/node/" + l_node.id.out + "/edit"), primary_tabs)
f.append_to_html (wsf_theme, b)
end
else
b.append ("<h1>Access denied</h1>")
end
else
set_title ("Unknown node")
end
elseif
attached {WSF_STRING} request.path_parameter ("type") as p_type and then
attached node_api.content_type (p_type.value) as l_type
then
if has_permission ("create " + l_type.name) then
if attached l_type.new_node (Void) as l_node then
f := edit_form (l_node, url (request.path_info, Void), "edit-" + l_type.name, l_type)
if request.is_post_request_method then
f.validation_actions.extend (agent edit_form_validate (?, b))
f.submit_actions.extend (agent edit_form_submit (?, l_node, l_type, b))
f.process (Current)
fd := f.last_data
end
set_title ("Edit #" + l_node.id.out)
add_to_menu (create {CMS_LOCAL_LINK}.make ("View", node_url (l_node)), primary_tabs)
@@ -66,11 +101,12 @@ feature -- Execution
f.append_to_html (wsf_theme, b)
else
b.append ("<h1>Access denied</h1>")
b.append ("<h1>Server error</h1>")
end
else
set_title ("Unknown node")
b.append ("<h1>Access denied</h1>")
end
else
set_title ("Create new content ...")
b.append ("<ul id=%"content-types%">")
@@ -140,10 +176,17 @@ feature -- Form
end
if a_node /= Void then
l_node := a_node
change_node (a_type, fd, a_node)
s := "modified"
if l_node.has_id then
change_node (a_type, fd, a_node)
s := "modified"
else
change_node (a_type, fd, a_node)
l_node.set_author (user)
s := "created"
end
else
l_node := new_node (a_type, fd, Void)
l_node.set_author (user)
s := "created"
end
node_api.save_node (l_node)

View File

@@ -129,10 +129,10 @@ feature -- HTTP Methods
elseif l_nid > 0 then --| i.e: l_node = Void
send_not_found (req, res)
else
send_bad_request (req, res)
-- send_bad_request (req, res)
-- FIXME: should not be accepted
-- Factory
-- create_new_node (req, res)
create_new_node (req, res)
end
end
end
@@ -145,6 +145,9 @@ feature -- HTTP Methods
if req.path_info.ends_with_general ("/edit") then
create edit_response.make (req, res, api, node_api)
edit_response.execute
elseif req.path_info.starts_with_general ("/node/add/") then
create edit_response.make (req, res, api, node_api)
edit_response.execute
else
to_implement ("Check user permissions!!!")
if attached current_user (req) as l_user then
@@ -293,14 +296,52 @@ feature {NONE} -- Node
create_new_node (req: WSF_REQUEST; res: WSF_RESPONSE)
local
l_page: CMS_RESPONSE
l_page: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE
l_node: detachable CMS_NODE
l_gen_page: GENERIC_VIEW_CMS_RESPONSE
edit_response: NODE_FORM_RESPONSE
s: STRING
do
if api.user_has_permission (current_user (req), "create node") then
create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
l_page.execute
if
attached {WSF_STRING} req.path_parameter ("type") as p_type and then
attached node_api.content_type (p_type.value) as ct
then
create edit_response.make (req, res, api, node_api)
edit_response.execute
-- create l_page.make (req, res, api)
-- l_node := ct.new_node (Void)
-- l_page.set_main_content (l_node.out)
-- l_page.execute
else
send_access_denied (req, res)
create l_gen_page.make (req, res, api)
create s.make_empty
s.append ("<ul>")
across
node_api.content_types as ic
loop
if api.user_has_permission (current_user (req), "create " + ic.item.name) then
s.append ("<li>")
s.append (l_gen_page.link (ic.item.title, node_api.new_content_path (ic.item), Void))
if attached ic.item.description as l_description then
s.append ("<p class=%"description%">")
s.append (l_gen_page.html_encoded (l_description))
s.append ("</p>")
end
s.append ("</li>")
end
end
s.append ("</ul>")
l_gen_page.set_title ("Create new content ...")
l_gen_page.set_main_content (s)
l_gen_page.execute
end
-- if api.user_has_permission (current_user (req), "create node") then
-- create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
-- l_page.execute
-- else
-- send_access_denied (req, res)
-- end
end
feature -- {NONE} Form data

View File

@@ -133,15 +133,15 @@ feature -- Access: router
l_methods: WSF_REQUEST_METHODS
do
create l_node_handler.make (a_api, a_node_api)
create l_methods
l_methods.enable_get
l_methods.enable_post
l_methods.lock
a_router.handle_with_request_methods ("/node", l_node_handler, l_methods)
a_router.handle_with_request_methods ("/node", l_node_handler, a_router.methods_get_post)
a_router.handle_with_request_methods ("/node/", l_node_handler, a_router.methods_get_post)
create l_new_node_handler.make (a_api, a_node_api)
a_router.handle_with_request_methods ("/node/new/{type}", create {WSF_URI_AGENT_HANDLER}.make (agent do_get_node_creation_by_type (?,?, "type", a_node_api)), a_router.methods_get)
a_router.handle_with_request_methods ("/node/new", create {WSF_URI_AGENT_HANDLER}.make (agent do_get_node_creation_selection (?,?, a_node_api)), a_router.methods_get)
a_router.handle_with_request_methods ("/node/add/{type}", l_new_node_handler, a_router.methods_get_post)
a_router.handle_with_request_methods ("/node/new", l_new_node_handler, a_router.methods_get)
-- a_router.handle_with_request_methods ("/node/new/{type}", create {WSF_URI_AGENT_HANDLER}.make (agent do_get_node_creation_by_type (?,?, "type", a_node_api)), a_router.methods_get)
-- a_router.handle_with_request_methods ("/node/new", create {WSF_URI_AGENT_HANDLER}.make (agent do_get_node_creation_selection (?,?, a_node_api)), a_router.methods_get)
create l_edit_node_handler.make (a_api, a_node_api)
a_router.handle_with_request_methods ("/node/{id}/edit", l_edit_node_handler, a_router.methods_get_post)
@@ -149,6 +149,8 @@ feature -- Access: router
create l_node_handler.make (a_api, a_node_api)
a_router.handle_with_request_methods ("/node/{id}", l_node_handler, a_router.methods_get_put_delete + a_router.methods_get_post)
-- Nodes
create l_nodes_handler.make (a_api, a_node_api)
create l_methods
@@ -261,51 +263,53 @@ feature -- Hooks
do
create lnk.make ("List of nodes", a_response.url ("/nodes", Void))
a_menu_system.primary_menu.extend (lnk)
create lnk.make ("Create ..", a_response.url ("/node/", Void))
a_menu_system.primary_menu.extend (lnk)
end
feature -- Handler
--feature -- Handler
do_get_node_creation_selection (req: WSF_REQUEST; res: WSF_RESPONSE; a_node_api: CMS_NODE_API)
local
l_page: GENERIC_VIEW_CMS_RESPONSE
s: STRING
do
create l_page.make (req, res, a_node_api.cms_api)
-- do_get_node_creation_selection (req: WSF_REQUEST; res: WSF_RESPONSE; a_node_api: CMS_NODE_API)
-- local
-- l_page: GENERIC_VIEW_CMS_RESPONSE
-- s: STRING
-- do
-- create l_page.make (req, res, a_node_api.cms_api)
create s.make_empty
s.append ("<ul>")
across
a_node_api.content_types as ic
loop
s.append ("<li>")
s.append (l_page.link (ic.item.title, a_node_api.new_content_path (ic.item), Void))
if attached ic.item.description as l_description then
s.append ("<p class=%"description%">")
s.append (l_page.html_encoded (l_description))
s.append ("</p>")
end
s.append ("</li>")
end
s.append ("</ul>")
l_page.set_title ("Create new content ...")
l_page.set_main_content (s)
l_page.execute
end
-- create s.make_empty
-- s.append ("<ul>")
-- across
-- a_node_api.content_types as ic
-- loop
-- s.append ("<li>")
-- s.append (l_page.link (ic.item.title, a_node_api.new_content_path (ic.item), Void))
-- if attached ic.item.description as l_description then
-- s.append ("<p class=%"description%">")
-- s.append (l_page.html_encoded (l_description))
-- s.append ("</p>")
-- end
-- s.append ("</li>")
-- end
-- s.append ("</ul>")
-- l_page.set_title ("Create new content ...")
-- l_page.set_main_content (s)
-- l_page.execute
-- end
do_get_node_creation_by_type (req: WSF_REQUEST; res: WSF_RESPONSE; a_type_varname: READABLE_STRING_8; a_node_api: CMS_NODE_API)
local
l_page: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE
l_node: detachable CMS_NODE
do
create l_page.make (req, res, a_node_api.cms_api)
if
attached {WSF_STRING} req.path_parameter (a_type_varname) as p_type and then
attached a_node_api.content_type (p_type.value) as ct
then
l_node := ct.new_node (Void)
l_page.set_main_content (l_node.out)
end
l_page.execute
end
-- do_get_node_creation_by_type (req: WSF_REQUEST; res: WSF_RESPONSE; a_type_varname: READABLE_STRING_8; a_node_api: CMS_NODE_API)
-- local
-- l_page: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE
-- l_node: detachable CMS_NODE
-- do
-- create l_page.make (req, res, a_node_api.cms_api)
-- if
-- attached {WSF_STRING} req.path_parameter (a_type_varname) as p_type and then
-- attached a_node_api.content_type (p_type.value) as ct
-- then
-- l_node := ct.new_node (Void)
-- l_page.set_main_content (l_node.out)
-- end
-- l_page.execute
-- end
end