kodekopelli 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +3 -0
- data/LICENSE +32 -0
- data/README +78 -0
- data/Rakefile +87 -0
- data/bin/kodekopelli +5 -0
- data/examples/faqomatic/config.xml +40 -0
- data/examples/faqomatic/content.rhtml +376 -0
- data/examples/faqomatic/generated/README.txt +1 -0
- data/examples/faqomatic/includes/shampoo_answer.txt +1 -0
- data/examples/faqomatic/templates/faqs.txt +22 -0
- data/examples/faqomatic/templates/great_big.txt +3 -0
- data/examples/faqomatic/templates/html_wrapper.txt +9 -0
- data/examples/thankyounotes/config.xml +18 -0
- data/examples/thankyounotes/content.rhtml +528 -0
- data/examples/thankyounotes/generated/README.txt +1 -0
- data/examples/thankyounotes/includes/poem.txt +3 -0
- data/examples/thankyounotes/templates/thanks.txt +14 -0
- data/examples/treemenu/config.xml +110 -0
- data/examples/treemenu/content.rhtml +324 -0
- data/examples/treemenu/generated/README.txt +1 -0
- data/examples/treemenu/templates/authorized.txt +1 -0
- data/examples/treemenu/templates/menu_category.txt +4 -0
- data/examples/treemenu/templates/menu_item.txt +3 -0
- data/examples/treemenu/templates/simple_menu.txt +3 -0
- data/lib/kodekopelli.rb +56 -0
- data/lib/kodekopelli/expandable_properties.rb +63 -0
- data/lib/kodekopelli/file_generator.rb +726 -0
- data/lib/kodekopelli/frozen_key_hash.rb +67 -0
- data/lib/kodekopelli/minimal_logger.rb +50 -0
- data/lib/kodekopelli/properties_file.rb +41 -0
- data/lib/kodekopelli/util.rb +30 -0
- data/rakefile +87 -0
- data/test/abstract_unit.rb +4 -0
- data/test/fixtures/definitions/invalid/empty +0 -0
- data/test/fixtures/definitions/invalid/gibberish.txt +6 -0
- data/test/fixtures/definitions/kodekopelli.xsd +95 -0
- data/test/fixtures/definitions/valid/empty_files.xml +49 -0
- data/test/fixtures/definitions/valid/kodekopelli_rocks_files.xml +359 -0
- data/test/fixtures/definitions/valid/simplest.xml +8 -0
- data/test/fixtures/includes/bang.txt +1 -0
- data/test/fixtures/includes/c.txt +1 -0
- data/test/fixtures/includes/d.txt +1 -0
- data/test/fixtures/includes/e.txt +1 -0
- data/test/fixtures/includes/empty.txt +0 -0
- data/test/fixtures/includes/i.txt +1 -0
- data/test/fixtures/includes/k.txt +1 -0
- data/test/fixtures/includes/k_upper.txt +1 -0
- data/test/fixtures/includes/kodekopelli_rocks.txt +1 -0
- data/test/fixtures/includes/l.txt +1 -0
- data/test/fixtures/includes/o.txt +1 -0
- data/test/fixtures/includes/p.txt +1 -0
- data/test/fixtures/includes/r.txt +1 -0
- data/test/fixtures/includes/s.txt +1 -0
- data/test/fixtures/includes/space.txt +1 -0
- data/test/fixtures/properties/comments.properties +17 -0
- data/test/fixtures/properties/empty.properties +0 -0
- data/test/fixtures/properties/expandable.properties +2 -0
- data/test/fixtures/properties/none_valid.properties +1 -0
- data/test/fixtures/properties/simple.properties +5 -0
- data/test/fixtures/templates/anything_att.txt +1 -0
- data/test/fixtures/templates/anything_att_prop.txt +1 -0
- data/test/fixtures/templates/anything_prop.txt +1 -0
- data/test/fixtures/templates/anything_prop_att.txt +1 -0
- data/test/fixtures/templates/blank.txt +0 -0
- data/test/fixtures/templates/child_output.txt +1 -0
- data/test/fixtures/templates/kodekopelli_blanks +1 -0
- data/test/tc_expandable_properties.rb +106 -0
- data/test/tc_file_generator.rb +20 -0
- data/test/tc_frozen_key_hash.rb +34 -0
- data/test/tc_properties_file.rb +52 -0
- data/test/tc_util.rb +55 -0
- data/test/ts_all_tests.rb +9 -0
- data/test/ts_functional.rb +86 -0
- metadata +133 -0
@@ -0,0 +1 @@
|
|
1
|
+
This folder contains all content generated by Kodekopelli processing.
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<%= include_file(att('poem')) %>
|
2
|
+
|
3
|
+
<%= Time.now.strftime("%B %d, %Y") %>
|
4
|
+
|
5
|
+
Dear <%= att('to', 'Friend') %>,
|
6
|
+
|
7
|
+
Thank-you very much for <%= att('purpose', 'everything') %>.
|
8
|
+
|
9
|
+
<%= att('closing', 'Yours Truly') %>,
|
10
|
+
|
11
|
+
<%= att('from', 'Kodekopelli') %>
|
12
|
+
<% unless att('ps',nil).nil? %>
|
13
|
+
P.S. <%= att('ps') %>
|
14
|
+
<% end %>
|
@@ -0,0 +1,110 @@
|
|
1
|
+
<kodekopelli
|
2
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
3
|
+
xsi:noNamespaceSchemaLocation="http://www.kodekopelli.org/xml/schemas/kodekopelli.xsd">
|
4
|
+
<!-- Project structure properties. These locations should
|
5
|
+
already exist. -->
|
6
|
+
<property location="." name="basedir" />
|
7
|
+
<!-- Folder containing Kodekopelli templates. -->
|
8
|
+
<property location="${basedir}/templates"
|
9
|
+
name="template.dir" />
|
10
|
+
<!-- Folder that should contain all Kodekopelli output. -->
|
11
|
+
<property location="${basedir}/generated"
|
12
|
+
name="output.dir" />
|
13
|
+
<!-- Templates -->
|
14
|
+
<property location="${template.dir}/simple_menu.txt"
|
15
|
+
name="menu" />
|
16
|
+
<property location="${template.dir}/menu_category.txt"
|
17
|
+
name="category" />
|
18
|
+
<property location="${template.dir}/menu_item.txt"
|
19
|
+
name="item" />
|
20
|
+
<property location="${template.dir}/authorized.txt"
|
21
|
+
name="authorized" />
|
22
|
+
<!-- URLs -->
|
23
|
+
<property name="admin.home.url" value="[URL GOES HERE]" />
|
24
|
+
<property name="add.user.url" value="[URL GOES HERE]" />
|
25
|
+
<property name="change.user.url" value="[URL GOES HERE]" />
|
26
|
+
<property name="delete.user.url" value="[URL GOES HERE]" />
|
27
|
+
<property name="admin.sys.url" value="[URL GOES HERE]" />
|
28
|
+
<property name="admin.user.url" value="[URL GOES HERE]" />
|
29
|
+
<property name="site.statistics.url"
|
30
|
+
value="[URL GOES HERE]" />
|
31
|
+
<property name="server.status.url" value="[URL GOES HERE]" />
|
32
|
+
<property name="auditing.url" value="[URL GOES HERE]" />
|
33
|
+
<property name="hr.home.url" value="[URL GOES HERE]" />
|
34
|
+
<property name="some.hr.url" value="[URL GOES HERE]" />
|
35
|
+
<property name="another.hr.url" value="[URL GOES HERE]" />
|
36
|
+
<property name="public.item.one.url"
|
37
|
+
value="[URL GOES HERE]" />
|
38
|
+
<property name="public.item.two.url"
|
39
|
+
value="[URL GOES HERE]" />
|
40
|
+
<property name="marketing.home.url"
|
41
|
+
value="[URL GOES HERE]" />
|
42
|
+
<property name="some.marketing.url"
|
43
|
+
value="[URL GOES HERE]" />
|
44
|
+
<filegroup>
|
45
|
+
<!-- The main menu. -->
|
46
|
+
<file name="${output.dir}/main_menu.jsp">
|
47
|
+
<composite template="${menu}">
|
48
|
+
<composite template="${category}"
|
49
|
+
text="Public Menu Category">
|
50
|
+
<composite template="${menu}">
|
51
|
+
<template target="_blank" template="${item}" text="Public Item One"
|
52
|
+
url="${public.item.one.url}" />
|
53
|
+
<template template="${item}" text="Public Item Two"
|
54
|
+
url="${public.item.two.url}" />
|
55
|
+
</composite>
|
56
|
+
</composite>
|
57
|
+
<composite roles="ROLE_MARKETING"
|
58
|
+
template="${authorized}">
|
59
|
+
<composite target="_blank" template="${category}"
|
60
|
+
text="Marketing Menu Category"
|
61
|
+
url="${marketing.home.url}">
|
62
|
+
<composite template="${menu}">
|
63
|
+
<template template="${item}" text="Marketing Item One" url="${some.marketing.url}" />
|
64
|
+
</composite>
|
65
|
+
</composite>
|
66
|
+
</composite>
|
67
|
+
<composite roles="ROLE_HUMAN_RESOURCES"
|
68
|
+
template="${authorized}">
|
69
|
+
<composite target="_blank" template="${category}"
|
70
|
+
text="Human Resources Menu Category"
|
71
|
+
url="${hr.home.url}">
|
72
|
+
<composite template="${menu}">
|
73
|
+
<template template="${item}" text="HR Item One" url="${some.hr.url}" />
|
74
|
+
<template template="${item}" text="HR Item Two" url="${another.hr.url}" />
|
75
|
+
</composite>
|
76
|
+
</composite>
|
77
|
+
</composite>
|
78
|
+
<composite roles="ROLE_SYS_ADMIN"
|
79
|
+
template="${authorized}">
|
80
|
+
<composite target="_blank" template="${category}"
|
81
|
+
text="Amin Menu Category"
|
82
|
+
url="${admin.home.url}">
|
83
|
+
<composite template="${menu}">
|
84
|
+
<composite target="_blank"
|
85
|
+
template="${category}"
|
86
|
+
text="User Administration Menu Category"
|
87
|
+
url="${admin.user.url}">
|
88
|
+
<composite template="${menu}">
|
89
|
+
<template template="${item}" text="Add User" url="${add.user.url}" />
|
90
|
+
<template template="${item}" text="Change User" url="${change.user.url}" />
|
91
|
+
<template template="${item}" text="Delete User" url="${delete.user.url}" />
|
92
|
+
</composite>
|
93
|
+
</composite>
|
94
|
+
<composite target="_blank"
|
95
|
+
template="${category}"
|
96
|
+
text="System Administration Menu Category"
|
97
|
+
url="${admin.sys.url}">
|
98
|
+
<composite template="${menu}">
|
99
|
+
<template template="${item}" text="Auditing" url="${auditing.url}" />
|
100
|
+
<template template="${item}" text="Site Statistics" url="${site.statistics.url}" />
|
101
|
+
<template template="${item}" text="Server Status" url="${server.status.url}" />
|
102
|
+
</composite>
|
103
|
+
</composite>
|
104
|
+
</composite>
|
105
|
+
</composite>
|
106
|
+
</composite>
|
107
|
+
</composite>
|
108
|
+
</file>
|
109
|
+
</filegroup>
|
110
|
+
</kodekopelli>
|
@@ -0,0 +1,324 @@
|
|
1
|
+
<p class="note">
|
2
|
+
<strong>Please Note</strong> This example should be considered a work in progress.
|
3
|
+
Although all associated configuration files and templates have been completed and
|
4
|
+
are included in this example, not all supporting text has been added.
|
5
|
+
</p>
|
6
|
+
<p>
|
7
|
+
This simple example demonstrates basic Kodekopelli functionality
|
8
|
+
and recommended practices. The following Kodekopelli concepts
|
9
|
+
not covered by previous examples are illustrated herein:
|
10
|
+
</p>
|
11
|
+
<ul>
|
12
|
+
<li>
|
13
|
+
Integrating other view layer technologies
|
14
|
+
(JSP custom tags) in Kodekopelli templates.
|
15
|
+
</li>
|
16
|
+
<li>
|
17
|
+
Nesting <a href="<%= att 'manual' %>#composites">composite</a>
|
18
|
+
elements in Kodekopelli configuration files.
|
19
|
+
</li>
|
20
|
+
</ul>
|
21
|
+
<p>
|
22
|
+
Unlike the introductory examples (<a href="/examples/thankyounotes">Thank-You Notes</a>
|
23
|
+
and <a href="/examples/faqomatic">FAQ-O-Matic</a>),
|
24
|
+
this example doesn't strive to impart deep knowledge of the Kodekopelli
|
25
|
+
directives used herein; rather, it presents those templates and configuration
|
26
|
+
files necessary to achieve the goal state shown below.
|
27
|
+
</p>
|
28
|
+
<h2>Problem</h2>
|
29
|
+
<p>
|
30
|
+
Several sites on your corporate intranet make use of complex tree menus.
|
31
|
+
Each menu is composed of one (1) or more top level menu categories and
|
32
|
+
each menu category is composed of one (1) or more menu items or additional
|
33
|
+
categories. Further, the menus often must nest to three (3) or four (4)
|
34
|
+
levels deep. To complicate things even more, each menu category and menu item
|
35
|
+
may need to be wrapped, individually, with one or more JSP custom tags that provide
|
36
|
+
access control, among other things. When combined with significant CSS
|
37
|
+
directives, your menu-related JSPs have become unwieldy and prone to human
|
38
|
+
error.
|
39
|
+
</p>
|
40
|
+
<h2>Solution</h2>
|
41
|
+
<p>
|
42
|
+
Use Kodekopelli as an additional layer of abstraction for
|
43
|
+
generating tree menu JSP fragments. The relevant menu-related
|
44
|
+
entries in the Kodekopelli configuration file(s) will then
|
45
|
+
serve as a kind of
|
46
|
+
<a href="http://en.wikipedia.org/wiki/Domain_Specific_Language"
|
47
|
+
target="">domain-specific language</a> that is easily
|
48
|
+
modifiable by humans, leaving the tedious process of JSP construction
|
49
|
+
to Kodekopelli.
|
50
|
+
</p>
|
51
|
+
<h3>Project Structure</h3>
|
52
|
+
<p>
|
53
|
+
As with the previous examples, those files that Kodekopelli
|
54
|
+
<em>generates</em> will be separated from those
|
55
|
+
that he uses to generate said files. Starting from a fresh, empty folder
|
56
|
+
of your choice, create subfolders mirroring the following structure:
|
57
|
+
</p>
|
58
|
+
<pre class="code">
|
59
|
+
/generated
|
60
|
+
/templates
|
61
|
+
</pre>
|
62
|
+
<h3>The Goal</h3>
|
63
|
+
<ul>
|
64
|
+
<li>
|
65
|
+
Public Menu Category
|
66
|
+
<br />
|
67
|
+
<ul>
|
68
|
+
<li>
|
69
|
+
<a href="" target="">
|
70
|
+
Public Item One
|
71
|
+
</a>
|
72
|
+
</li>
|
73
|
+
<li>
|
74
|
+
<a href="" target="">
|
75
|
+
Public Item Two
|
76
|
+
</a>
|
77
|
+
</li>
|
78
|
+
</ul>
|
79
|
+
</li>
|
80
|
+
<li>
|
81
|
+
<a href="" target="">
|
82
|
+
Marketing Menu Category
|
83
|
+
</a>
|
84
|
+
<br />
|
85
|
+
<ul>
|
86
|
+
<li>
|
87
|
+
<a href="" target="">
|
88
|
+
Marketing Item One
|
89
|
+
</a>
|
90
|
+
</li>
|
91
|
+
</ul>
|
92
|
+
</li>
|
93
|
+
<li>
|
94
|
+
<a href="" target="">
|
95
|
+
Human Resources Menu Category
|
96
|
+
</a>
|
97
|
+
<br />
|
98
|
+
<ul>
|
99
|
+
<li>
|
100
|
+
<a href="" target="">
|
101
|
+
HR Item One
|
102
|
+
</a>
|
103
|
+
</li>
|
104
|
+
<li>
|
105
|
+
<a href="" target="">
|
106
|
+
HR Item Two
|
107
|
+
</a>
|
108
|
+
</li>
|
109
|
+
</ul>
|
110
|
+
</li>
|
111
|
+
<li>
|
112
|
+
<a href="" target="">
|
113
|
+
Amin Menu Category
|
114
|
+
</a>
|
115
|
+
<br />
|
116
|
+
<ul>
|
117
|
+
<li>
|
118
|
+
<a href="" target="">
|
119
|
+
User Administration Menu Category
|
120
|
+
</a>
|
121
|
+
<br />
|
122
|
+
<ul>
|
123
|
+
<li>
|
124
|
+
<a href="" target="">
|
125
|
+
Add User
|
126
|
+
</a>
|
127
|
+
</li>
|
128
|
+
<li>
|
129
|
+
<a href="" target="">
|
130
|
+
Change User
|
131
|
+
</a>
|
132
|
+
</li>
|
133
|
+
<li>
|
134
|
+
<a href="" target="">
|
135
|
+
Delete User
|
136
|
+
</a>
|
137
|
+
</li>
|
138
|
+
</ul>
|
139
|
+
</li>
|
140
|
+
<li>
|
141
|
+
<a href="" target="">
|
142
|
+
System Administration Menu Category
|
143
|
+
</a>
|
144
|
+
<br />
|
145
|
+
<ul>
|
146
|
+
<li>
|
147
|
+
<a href="" target="">
|
148
|
+
Auditing
|
149
|
+
</a>
|
150
|
+
</li>
|
151
|
+
<li>
|
152
|
+
<a href="" target="">
|
153
|
+
Site Statistics
|
154
|
+
</a>
|
155
|
+
</li>
|
156
|
+
<li>
|
157
|
+
<a href="" target="">
|
158
|
+
Server Status
|
159
|
+
</a>
|
160
|
+
</li>
|
161
|
+
</ul>
|
162
|
+
</li>
|
163
|
+
</ul>
|
164
|
+
</li>
|
165
|
+
</ul>
|
166
|
+
<h3>Templates</h3>
|
167
|
+
<p>
|
168
|
+
The menu shown above may be created using four simple templates, described
|
169
|
+
below.
|
170
|
+
</p>
|
171
|
+
<h4>Simple Menu Template</h4>
|
172
|
+
<pre class="code">
|
173
|
+
<ul><% child_iterator { |current_child, text| %>
|
174
|
+
<%= text %><% } %>
|
175
|
+
</ul>
|
176
|
+
</pre>
|
177
|
+
<h4>Menu Category Template</h4>
|
178
|
+
<pre class="code">
|
179
|
+
<li><% unless att('url',nil).nil? %><a href="<%= att('url') %>"
|
180
|
+
target="<%= att('target') %>"
|
181
|
+
><% end %><%= h att('text') %><% unless att('url',nil).nil? %></a><% end %><br />
|
182
|
+
<%= child_output %></li>
|
183
|
+
</pre>
|
184
|
+
<h4>Menu Item Template</h4>
|
185
|
+
<pre class="code">
|
186
|
+
<li><% unless att('url',nil).nil? %><a href="<%= att('url') %>"
|
187
|
+
target="<%= att('target') %>"
|
188
|
+
><% end %><%= h att('text') %><% unless att('url',nil).nil? %></a><% end %></li>
|
189
|
+
</pre>
|
190
|
+
<h4>Authorization Control Template</h4>
|
191
|
+
<p>
|
192
|
+
This template leverages the <em>authz</em> JSP custom tag library provided by
|
193
|
+
the open source <a href="http://acegisecurity.sourceforge.net/"
|
194
|
+
target="_blank">Acegi Security System</a>.
|
195
|
+
</p>
|
196
|
+
<pre class="code">
|
197
|
+
<authz:authorize ifAnyGranted="<%= att('roles') %>"><%= child_output %></authz:authorize>
|
198
|
+
</pre>
|
199
|
+
<h3>Configuration File</h3>
|
200
|
+
<p>
|
201
|
+
The completed Kodekopelli configuration file is shown, in its entirety,
|
202
|
+
below.
|
203
|
+
</p>
|
204
|
+
<pre class="code">
|
205
|
+
<kodekopelli>
|
206
|
+
<!-- Project structure properties. These locations should
|
207
|
+
already exist. -->
|
208
|
+
<property location="." name="basedir" />
|
209
|
+
<!-- Folder containing Kodekopelli templates. -->
|
210
|
+
<property location="${basedir}/templates"
|
211
|
+
name="template.dir" />
|
212
|
+
<!-- Folder that should contain all Kodekopelli output. -->
|
213
|
+
<property location="${basedir}/generated"
|
214
|
+
name="output.dir" />
|
215
|
+
<!-- Templates -->
|
216
|
+
<property location="${template.dir}/simple_menu.txt"
|
217
|
+
name="menu" />
|
218
|
+
<property location="${template.dir}/menu_category.txt"
|
219
|
+
name="category" />
|
220
|
+
<property location="${template.dir}/menu_item.txt"
|
221
|
+
name="item" />
|
222
|
+
<property location="${template.dir}/authorized.txt"
|
223
|
+
name="authorized" />
|
224
|
+
<!-- URLs -->
|
225
|
+
<property name="admin.home.url" value="[URL GOES HERE]" />
|
226
|
+
<property name="add.user.url" value="[URL GOES HERE]" />
|
227
|
+
<property name="change.user.url" value="[URL GOES HERE]" />
|
228
|
+
<property name="delete.user.url" value="[URL GOES HERE]" />
|
229
|
+
<property name="admin.sys.url" value="[URL GOES HERE]" />
|
230
|
+
<property name="admin.user.url" value="[URL GOES HERE]" />
|
231
|
+
<property name="site.statistics.url"
|
232
|
+
value="[URL GOES HERE]" />
|
233
|
+
<property name="server.status.url" value="[URL GOES HERE]" />
|
234
|
+
<property name="auditing.url" value="[URL GOES HERE]" />
|
235
|
+
<property name="hr.home.url" value="[URL GOES HERE]" />
|
236
|
+
<property name="some.hr.url" value="[URL GOES HERE]" />
|
237
|
+
<property name="another.hr.url" value="[URL GOES HERE]" />
|
238
|
+
<property name="public.item.one.url"
|
239
|
+
value="[URL GOES HERE]" />
|
240
|
+
<property name="public.item.two.url"
|
241
|
+
value="[URL GOES HERE]" />
|
242
|
+
<property name="marketing.home.url"
|
243
|
+
value="[URL GOES HERE]" />
|
244
|
+
<property name="some.marketing.url"
|
245
|
+
value="[URL GOES HERE]" />
|
246
|
+
<filegroup>
|
247
|
+
<!-- The main menu. -->
|
248
|
+
<file name="${output.dir}/main_menu.jsp">
|
249
|
+
<composite template="${menu}">
|
250
|
+
<composite template="${category}"
|
251
|
+
text="Public Menu Category">
|
252
|
+
<composite template="${menu}">
|
253
|
+
<template target="_blank" template="${item}" text="Public Item One"
|
254
|
+
url="${public.item.one.url}" />
|
255
|
+
<template template="${item}" text="Public Item Two"
|
256
|
+
url="${public.item.two.url}" />
|
257
|
+
</composite>
|
258
|
+
</composite>
|
259
|
+
<composite roles="ROLE_MARKETING"
|
260
|
+
template="${authorized}">
|
261
|
+
<composite target="_blank" template="${category}"
|
262
|
+
text="Marketing Menu Category"
|
263
|
+
url="${marketing.home.url}">
|
264
|
+
<composite template="${menu}">
|
265
|
+
<template template="${item}" text="Marketing Item One" url="${some.marketing.url}" />
|
266
|
+
</composite>
|
267
|
+
</composite>
|
268
|
+
</composite>
|
269
|
+
<composite roles="ROLE_HUMAN_RESOURCES"
|
270
|
+
template="${authorized}">
|
271
|
+
<composite target="_blank" template="${category}"
|
272
|
+
text="Human Resources Menu Category"
|
273
|
+
url="${hr.home.url}">
|
274
|
+
<composite template="${menu}">
|
275
|
+
<template template="${item}" text="HR Item One" url="${some.hr.url}" />
|
276
|
+
<template template="${item}" text="HR Item Two" url="${another.hr.url}" />
|
277
|
+
</composite>
|
278
|
+
</composite>
|
279
|
+
</composite>
|
280
|
+
<composite roles="ROLE_SYS_ADMIN"
|
281
|
+
template="${authorized}">
|
282
|
+
<composite target="_blank" template="${category}"
|
283
|
+
text="Amin Menu Category"
|
284
|
+
url="${admin.home.url}">
|
285
|
+
<composite template="${menu}">
|
286
|
+
<composite target="_blank"
|
287
|
+
template="${category}"
|
288
|
+
text="User Administration Menu Category"
|
289
|
+
url="${admin.user.url}">
|
290
|
+
<composite template="${menu}">
|
291
|
+
<template template="${item}" text="Add User" url="${add.user.url}" />
|
292
|
+
<template template="${item}" text="Change User" url="${change.user.url}" />
|
293
|
+
<template template="${item}" text="Delete User" url="${delete.user.url}" />
|
294
|
+
</composite>
|
295
|
+
</composite>
|
296
|
+
<composite target="_blank"
|
297
|
+
template="${category}"
|
298
|
+
text="System Administration Menu Category"
|
299
|
+
url="${admin.sys.url}">
|
300
|
+
<composite template="${menu}">
|
301
|
+
<template template="${item}" text="Auditing" url="${auditing.url}" />
|
302
|
+
<template template="${item}" text="Site Statistics" url="${site.statistics.url}" />
|
303
|
+
<template template="${item}" text="Server Status" url="${server.status.url}" />
|
304
|
+
</composite>
|
305
|
+
</composite>
|
306
|
+
</composite>
|
307
|
+
</composite>
|
308
|
+
</composite>
|
309
|
+
</composite>
|
310
|
+
</file>
|
311
|
+
</filegroup>
|
312
|
+
</kodekopelli>
|
313
|
+
</pre>
|
314
|
+
<h2>Notes</h2>
|
315
|
+
<ul>
|
316
|
+
<li>
|
317
|
+
It would be very simple to enhance the templates to allow for specifying
|
318
|
+
CSS classes for all menu elements, allowing for greater control
|
319
|
+
over menu aesthetics. Numerous sites, like
|
320
|
+
<a href="http://css.maxdesign.com.au/listamatic/" target="">Listamatic</a>,
|
321
|
+
provide great examples for controlling the look and feel (LAF) of
|
322
|
+
menus based on unordered lists.
|
323
|
+
</li>
|
324
|
+
</ul>
|