diff --git a/ccm-portalserver/LICENSE b/ccm-portalserver/LICENSE new file mode 100644 index 000000000..4fb8f73c7 --- /dev/null +++ b/ccm-portalserver/LICENSE @@ -0,0 +1,454 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/ccm-portalserver/application.xml b/ccm-portalserver/application.xml new file mode 100644 index 000000000..1d1af2932 --- /dev/null +++ b/ccm-portalserver/application.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + A framework for personalized and group-oriented aggregation and delivery of + information. Portal Server relies on servlets to provide access to new and + existing applications in an organizations infrastructure and present the + information in a convenient centralized perspective. + + + diff --git a/ccm-portalserver/doc/archiving/archiving_SOW.html b/ccm-portalserver/doc/archiving/archiving_SOW.html new file mode 100644 index 000000000..bc1322e04 --- /dev/null +++ b/ccm-portalserver/doc/archiving/archiving_SOW.html @@ -0,0 +1,51 @@ + + + Archiving Statement of Work + + +

Portal Archiving - Statement Of Work

+

+by Jim Parsons - jparsons@redhat.com +

+This document details the intended approach to adding the ability to archive +portals for the Red Hat Enterprise Portal Server. +

+

+

+

Implementation Tasks

+ + + + diff --git a/ccm-portalserver/doc/subportal/subportal.html b/ccm-portalserver/doc/subportal/subportal.html new file mode 100644 index 000000000..148d85b5c --- /dev/null +++ b/ccm-portalserver/doc/subportal/subportal.html @@ -0,0 +1,166 @@ + + What has happened to Portal Server? + + +

What has happened to PortalServer?

+

+

Introduction

+This recent workcycle for Portal Server has introduced some significant +changes to both the architecture and the user interface of the product. Portal +Server now provides: + +This document describes in detail these and other recent changes to Portal Server. +

+

Architectural Changes

+There are two Architecturally significant changes to Portal Server in the +current workcycle. +

1) Support for Super/Sub Portals

+The roots of Portal Server can be found in the Ars Digita ECM Product. ECM was +primarily designed as a collaborative application that featured team workspaces. +Each registered user of ECM had a personal portal which they were free to +personalize, but the layout and styling choices of any other portal on the +system was fixed for every visitor to that portal. +

The Camden APLAWS contract presents a compelling new portal personalization +use case. APLAWS portals allow for partial personalization - for example, the +first column of an APLAWS portal may contain required portlets that every +visitor must have access to, but the other column(s) can be personally +configured by a registered user. What is more, this bahavior can be +switched on for any portal on the system. +

This functionality has been implemented in Portal Server as follows: +

+

The implementation of SuperPortals and SubPortals is very simple. Regular +portals, SubPortals and SuperPortals are all PortalSites. They are +distinguished only by persisted fields identifying the type of PortalSite. +Using database fields to distinguish PortalSite type has advantages over +class extension, as all 3 types appear in PortalSite collections, but can +easily be filtered if a particular type is desired. +

+

A word about locking cells in a Portal

+One of the challenges of this refactor was the fact that cell regions +within a PortalTab have no associated data structure. Column layout for a +PortalTab is persisted in a VARCHAR field within the PDL for a PortalTab. +Before this work cycle, there were 5 pre-defined layouts. The following +list provides a description of each layout, followed by the string +used to define the layout that is persisted in the database: + +The layout identifier string serves 2 purposes: First, the length of the +string is used by the local admin layout tab's PortletLayoutComponent class +to determine how many columns of Portlets will be rendered, and whether +or not to draw Portlet 'move position' arrows for Portlets, dependant on which +column they reside. Secondly, the layout string is added as an attribute to +the PortalTab's XML, so the style sheet knows what layout to draw.
+Difficulties arose when it was suddenly necessary to designate whether +a cell region in a PortalTab was locked from modification or not. +Removing this simple layout identity mechanism and replacing it with a full java +domain object and associated PDL would have been a very large task, as this +code would touch many files in the admin area as well as in the basic +Portal rendering code.
+The solution employed is to lowercase the character in the layout string that +corresponds to a locked cell region. If the layout chosen for a PortalTab +is narrow-wide-narrow, then the layout string would be 'NWN'. If the first +column or cell region is locked, then the persisted layout string would +be: 'nWN'. A 2-column wide-narrow layout, with no locked regions would be +stored as 'WN'. If both columns in the PortalTab were locked, the layout string +would be 'wn'. This approach to persisting information about locked +cell regions does not interfere with the first purpose of the layout string +described above. To insure styling still looks right, the code that sets +the layout attribute for the PortalTab now calls toUpper() on the layout +string before setting the layout class attr. +

The only new class types needed to implement Super/SubPortals are the +new SubPortalTab class, and the AgentPortlet class. Below please see the +figure describing changes to the Portal class structure. New classes +are filled in as pink.
+ +
+

+Here is a more detailed description of these two new classes. +

SubPortalTab.java

+SubPortalTab extends PortalTab, which extends the core Portal class. In Portal +is a method called getPortlets(), which returns a PortletCollection. When a +PortalTab is rendered, getPortlets() is called and the resulting set of +Portlets is iterated over and each Portlet's renderer is called.
+The PDL for SubPortalTab extends PortalTab and adds one column: an association +to the PortalTab in the SuperPortal that this particular SubPortalTab +corresponds to.
+SupPortalTab overrides getPortlets() and returns a PortletCollection that +is a union of Portlets that belong specifically to this SubPortal, along +with Portlets from the associated PortalTab in the SuperPortal that reside +in locked cells. The PortletCollection is built using a custom query called +query-SubPortalPortlets.pdl. +

+

AgentPortlet.java

+It is expected that a Portal that has been designated a SuperPortal may have +locked and unlocked cell regions. Unlocked cell regions will contain +Portlets that may be helpful to a user, but that may be replaced if desired. +If Portlets in unlocked regions have persistant data (and most Portlets do) +then it will be necessary for the Portlet and its data to be copied somehow. +Because there is currently no mechanism for data object copying, Portlets +can not be truly copied without implementing a custom clone method for each. +
+For this workcycle, rather than addressing issues that deep copying brings +up, an AgentPortlet has been constructed that acts as an agent for another +Portlet instance on the system. PDL for AgentPortlet contains an association +with a Portlet, and the AgentPortlet's doGetPortletRenderer() first +retrieves the associated Portlet, and then calls the associated +Portlet's doGetPortletRenderer() and passes the renderer through. The drawback +of this solution is that this type of Portlet cannot be individually +re-configured. If the user desires a different configuration for a Portlet +represented by an Agent, then they can create a new Portlet and configure +it themselves, and then delete the original AgentPortlet and its Portlet +reference. +

2) Enhanced Site-wide Admin UI

+In the initial release of PortalServer, there was no way to browse the entire +server for PortalSites. In addition, no UI was provided for deleting Portals, +and the only way that a child Portal could be created was within the +parent Portals local admin page. This work cycle has produced an enhanced +UI for sitewide management, mounted at /portal-admin/.
+Screen Captures and legends for the new admin ui follow below. + + + + diff --git a/ccm-portalserver/doc/subportal/subportal_arch.gif b/ccm-portalserver/doc/subportal/subportal_arch.gif new file mode 100644 index 000000000..cd46deee8 Binary files /dev/null and b/ccm-portalserver/doc/subportal/subportal_arch.gif differ diff --git a/ccm-portalserver/doc/use-cases/build_html_versions b/ccm-portalserver/doc/use-cases/build_html_versions new file mode 100644 index 000000000..b2e8bb423 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/build_html_versions @@ -0,0 +1,14 @@ +#!/bin/sh +rm ./html/*.html; +# +for x +do +java -cp ./saxon.jar com.icl.saxon.StyleSheet $x ./htmlize.xsl > ./html/$x.html; +done +# +echo "Building index page..."; +./build_index_page *.xml; +echo "Index page finished."; +# +echo "Finished conversion."; + diff --git a/ccm-portalserver/doc/use-cases/build_index_page b/ccm-portalserver/doc/use-cases/build_index_page new file mode 100644 index 000000000..68aa75416 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/build_index_page @@ -0,0 +1,39 @@ +#!/bin/sh +touch ./html/index.html; +rm ./html/index.html; +touch ./html/index.html; +echo "" >> ./html/index.html; +echo "" >> ./html/index.html; +echo "" >> ./html/index.html; +echo "CCM PORTAL Server - Use Cases" >> ./html/index.html; +echo "" >> ./html/index.html; +echo "" >> ./html/index.html; +echo "" >> ./html/index.html; +echo "" >> ./html/index.html; +echo "" >> ./html/index.html; +echo "" >> ./html/index.html; +echo "" >> ./html/index.html; +echo "
" >> ./html/index.html; +echo "" >> ./html/index.html; +echo "" >> ./html/index.html; +echo "

" >> ./html/index.html; +echo "" >> ./html/index.html; +echo "CCM Portal Server " >> ./html/index.html; +echo "" >> ./html/index.html; +echo "

" >> ./html/index.html; +echo "
" >> ./html/index.html; +echo "

" >> ./html/index.html; +echo "

" >> ./html/index.html; +echo "

Index of Portalserver Use Cases

" >> ./html/index.html; +# +for x +do +echo "" >> ./html/index.html; +java -cp ./saxon.jar com.icl.saxon.StyleSheet $x ./index.xsl >> ./html/index.html; +echo "" >> ./html/index.html; +echo "
" >> ./html/index.html; +done +# +echo "" >> ./html/index.html; +echo "" >> ./html/index.html; + diff --git a/ccm-portalserver/doc/use-cases/html/cw-use-cases.css b/ccm-portalserver/doc/use-cases/html/cw-use-cases.css new file mode 100644 index 000000000..d03e36ada --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/cw-use-cases.css @@ -0,0 +1,27 @@ +/* Use case styles */ + +.required { + font-style: normal; + font-weight: bold; + text-decoration: underline; +} + +.optional { + font-style: normal; + font-weight: bold; + +} + +.fix-me { + font-style: italic; +} + +DIV.sidelight { + background-color: #F0F0F0; + border: none; + padding: 5pt; +} + +TD.priority { + text-align: center; +} diff --git a/ccm-portalserver/doc/use-cases/html/developer.css b/ccm-portalserver/doc/use-cases/html/developer.css new file mode 100644 index 000000000..8158dabec --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/developer.css @@ -0,0 +1,171 @@ +/* arsdigita.css -- default style sheet */ + +BODY { + background-color: #FFFFFF; +} + +BODY, P, TD, TH, UL, OL { + font-family : Verdana, Arial, Helvetica, sans-serif; + font-size : 10pt; +} + +H1, H2, H3, H4 { + font-family : Verdana, Arial, Helvetica, sans-serif; +} + +H1 { + font-size : 120%; +} + +H2 { + font-size : 110%; +} + +H3, H4 { + font-size : 105%; +} + +/* +A:LINK { + text-decoration : none; + color : #0085C0; +} + +A:VISITED { + text-decoration : none; + color : Purple; +} + +A:HOVER { + text-decoration : underline; + color : #0085C0; +} + +A:LINK.leftcolnav { + text-decoration : none; + color : #0085C0; +} + +A:HOVER.leftcolnav { + text-decoration : none; + background : #999999; + color: black; +} + +A:VISITED.leftcolnav { + text-decoration : none; + color : Purple; +} +*/ + +.stripes { + font-size : 9pt; +} + +.navtopon { + background-color : #999999; + font-size : 9pt; + text-align : center; + font-weight : bold; +} + +.navtopoff { + font-size : 9pt; + text-align : center; + font-weight : bold; +} + +.gutter { + margin-top : 2mm; + margin-right : 3mm; + margin-bottom : 3mm; + margin-left : 5mm; +} + +.pagebodygutter { + margin-top : 2mm; +} + +.pagecentergutter { + margin-left : 25mm; + margin-right: 10mm; + margin-bottom: 2mm; + text-align : left; +} + + +.leftcolgutter { + margin-top : 2mm; + margin-right : 1mm; + margin-left : 3mm; +} + +.textcolgutter { + margin-bottom : 1.5mm; +} + +.textpromo { + font-size : 10pt; + margin-top : 2mm; + margin-right : 1mm; + margin-left : 2mm; +} + +.newscolgutter { + margin-left : 1mm; + margin-top : 2mm; + margin-bottom : 3mm; + font-size : 10pt; +} + +.itemgutter { + margin-left : 1.5mm; + font-size : 8pt; +} + +.logogutter { + margin-top : 3mm; + margin-bottom : 2mm; + margin-left : 3mm; +} + +.navtext { + font-size : 9pt; +} + +.note { + font-style : italic; + color : gray; +} + +.textwhite { + color : white; +} + +.small { + font-size : 9pt; +} + +.tiny { + font-size : 9pt; +} + +.confirmation { + color : Lime; +} + +.warning { + color : #ffcc66; +} + +.error { + color : Red; +} + +.disclaimer { + font-size : 9pt; + color : Gray; + margin-top : 1em; + margin-bottom : 1em; +} + diff --git a/ccm-portalserver/doc/use-cases/html/index.html b/ccm-portalserver/doc/use-cases/html/index.html new file mode 100644 index 000000000..6a01812f9 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/index.html @@ -0,0 +1,310 @@ + + + +CCM PORTAL Server - Use Cases + + + + + + + +
+ + +

+ +CCM Portal Server  + +

+
+

+

+

Index of Portalserver Use Cases

+ +00001 +   +Create a new portal +
+ +00002 +   +Create a New Portal from a Pre-defined Template +
+ +00003 +   +Create a Portal Template +
+ +00010 +   +Modify basic portal configuration +
+ +00011 +   +Modify Portal Mission +
+ +00012 +   +Modify Portal Name +
+ +00014 +   +Modify Portal URL Stub +
+ +00015 +   +Move Portal +
+ +00030 +   +Navigate to a related portal +
+ +00033 +   +Add another Portal as a Related Portal +
+ +00050 +   +Browse portal participants +
+ +00051 +   +Search for a portal participant +
+ +00052 +   +View/Administer a single participant +
+ +00055 +   +Add a portal participant +
+ +00056 +   +Remove a portal participant +
+ +00057 +   +Invite a participant to a portal +
+ +00065 +   +Modify a participant's role assignments +
+ +00100 +   +Add a Tab to a Portal +
+ +00110 +   +Configure A Portal Tab +
+ +00120 +   +Delete a Portal Tab +
+ +00140 +   +Change Name of Existing Portal Tab +
+ +00150 +   +Reorder Portal Tabs +
+ +00200 +   +Add a Portlet to a Portal Tab +
+ +00210 +   +Delete a Portlet from a Portal Tab +
+ +00220 +   +Change the Layout for a Portal Tab +
+ +00230 +   +Move a Portlet to a New Position Within a Portal Tab +
+ +00240 +   +Configure a Portlet +
+ +00310 +   +Add an Application to a Portal +
+ +00320 +   +Remove an Application from a Portal +
+ +00330 +   +Navigate to Applications Within a Portal +
+ +00340 +   +Configure an Application Instance +
+ +00400 +   +Create a Related Portal reference between two portals +
+ +00405 +   +Remove a Related Portal reference between two portals +
+ +00410 +   +Navigate to a related portal +
+ +00500 +   +Archive a Portal +
+ +00501 +   +Un-Archive a Portal +
+ +00610 +   +Navigate to a Personal Portal +
+ +00710 +   +View Help for the Current System Page +
+ +00730 +   +Navigate Help Using a Table of Contents +
+ +00740 +   +Search Help Using a Keyword +
+ +00750 +   +Search Help Using a Text String +
+ +00810 +   +Browsing Bookmarks within a Portal +
+ +00820 +   +Adding a Bookmark +
+ +00830 +   +Editing Bookmark Properties +
+ +00840 +   +Deleting a Bookmark +
+ +00900 +   +Select a Theme for a Portal +
+ +00910 +   +Create a Theme for a Portal +
+ +00951 +   +Set Context Bar Color for Theme +
+ +00952 +   +Set Active Tab Color for Theme +
+ +00953 +   +Set Inactive Tab Color for Theme +
+ +00954 +   +Set Active Tab Text Color for Theme +
+ +00955 +   +Set Inactive Tab Text Color for Theme +
+ +00956 +   +Set Top Rule Under Tabs Color for Theme +
+ +00957 +   +Set Top Rule No Tabs Color for Theme +
+ +00958 +   +Set Bottom Rule Color for Theme +
+ +00959 +   +Set Portlet Header Color for Theme +
+ +00960 +   +Set Portlet Icon Color for Theme +
+ + diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00001.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00001.xml.html new file mode 100644 index 000000000..a41f557bf --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00001.xml.html @@ -0,0 +1,210 @@ + + + + + Use Case 00001:Create a new portal + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00001:Create a new portal

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

The Portal Administrator makes new Portals available by performing the following steps:

+ +
    +
  • Creating a new portal.
  • +
  • Creating the group of Portal Participants for that portal.
  • +
  • Creating portal tabs, if desired, for the portal.
  • +
  • Adding the appropriate portlets to the portal and portal tabs.
  • +
  • Configuring layout and look & feel for the portal.
  • +
+ +

The Portal Administrator has two possible procedures for creating portals:

+ +
    +
  • Creating a new portal from scratch.
  • +
  • Creating a new portal by using a portal template. (See Alternate Paths)
  • +
+ +

While creating a portal, the Portal Administrator assigns the following properties:

+ +
    +
  • Portal Name - the name by which the portal is identified in the Web site.
  • +
  • Portal Mission - a brief description of the purpose that the portal is intended to fulfill.
  • +
  • Portal URL Label - the label of the Web site stub at which the portal appears.
  • +
+ + + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: The Portal Administrator wants to create a new portal
Preconditions: + +

User has general + permission to create portals. +

+ + + +
Basic Path: + +

+ +

    + +
  1. The Portal Administrator navigates to the creation interface + via the portal administration home page.
  2. + +
  3. She specifies a name for the portal.
  4. + +
  5. She specifies a URL stub for the portal.
  6. + +
  7. She optionally writes up a "mission statement" for the portal.
  8. + +
+ +

+ + + +
Postconditions: + +

A new portal is + created, with the user who created it identified as its + administrator.

+ + + +
Succesful End Conditions: + +

A new + portal is created, with the creating user named as a participant in + the portal with administrative privileges, and the Administrator is + redirected to the new portal's configuration page.

+ + + +
Alternate Paths: + + PA may choose to create a portal from an existing system template, rather than create a portal from scratch. See PSRV_00002:Create + a New Portal from a Pre-defined Template + + + +
Exception Paths: + +

+
    +
  • EXC-1: The Administrator does not have + permission to create new portals.
  • +
  • EXC-2: The specified URL stub contains + characters that are illegal for URLs.
  • +
  • EXC-3: The specified URL stub is already in + use by another portal.
  • +
+

+ + + +
Failure End Conditions: + +

+ + + +
Sample Narrative: + +

+ + + +
Open Issues:
Iteration: + Finished + +
Status: ready_for_review
+

+ by Eric Lorenzo +

+ Last Modified: 2001/11/06 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00002.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00002.xml.html new file mode 100644 index 000000000..d02975b16 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00002.xml.html @@ -0,0 +1,188 @@ + + + + + Use Case 00002:Create a New Portal from a Pre-defined Template + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00002:Create a New Portal from a Pre-defined Template

+

+

Release Target: 2.1

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

A Portal + Administrator may create a new portal from an existing template. She controls the portal's location in the portal hierarchy, + its name, its URL + stub, and its mission statement.

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: The Portal Administrator wants to create a new portal with pre-set applications, portlets, and layout as a starting point.
Preconditions: + + The user has general permission to create portals. + + +
Basic Path: + +

+ +

    + +
  1. The Portal Administrator navigates to the portal creation + interface via the portal administration home page.
  2. + +
  3. She specifies a name for the new portal.
  4. + +
  5. She specifies a URL stub for the new portal.
  6. + +
  7. She optionally writes up a "mission statement" for the new portal.
  8. + +
  9. She clicks the "Create from existing template" button.
  10. + +
  11. She is presented with a list of templates and selects the one she wishes to use for the new portal. If desired, she can + click the preview link of any template to visit a read-only version of that portal configuration.
  12. + +
  13. If there is a participant list associated with her template selection, she can check a checkbox which specifies whether + or not all participants associated with the template should be included in the new portal.
  14. + +
  15. Finally, she finishes by clicking the "Create Portal" button. + +
+

+ See PSRV-00002:Create a Portal Template for how to go about creating a template. + + + +
Postconditions: + +

+ + + +
Succesful End Conditions: + +

A new + portal is created, with the creating user named as a participant in + the portal with administrative privileges, and with all application + and portlet configuration copied over from the selected portal template. + Participants may be copied as well.

+ + + +
Alternate Paths: + +

+ + + +
Exception Paths: + +

+ + + +
Failure End Conditions: + +

+ + + +
Sample Narrative: + +

+ + + +
Open Issues: + +

+ + + +
Iteration: Facade
Status: not_started
+

+ by Jim Parsons +

+ Last Modified: 2003/02/28 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00003.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00003.xml.html new file mode 100644 index 000000000..9931d079a --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00003.xml.html @@ -0,0 +1,160 @@ + + + + + Use Case 00003:Create a Portal Template + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00003:Create a Portal Template

+

+

Release Target: 2.1

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

A Portal + Administrator may create and configure portal templates. +

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: The Portal Administrator wishes to create a new template
Preconditions: + +

User has general + permission to create portal templates.

+ + + +
Basic Path: + +

+ + To be determined... +

+ + + +
Postconditions: + +

A new portal template is created. +

+ + + +
Succesful End Conditions: + + + + +
Alternate Paths: + +

+ + +
Exception Paths: + + + + +
Failure End Conditions: + +

+ + + +
Sample Narrative: + +

+ +

Open Issues:

+ + + +
Open Issues:
Iteration: + Facade + +
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2001/11/06 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00010.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00010.xml.html new file mode 100644 index 000000000..657097537 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00010.xml.html @@ -0,0 +1,192 @@ + + + + + Use Case 00010:Modify basic portal configuration + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00010:Modify basic portal configuration

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

A Portal + Administrator may modify the basic configuration of its portal, + including its name, mission statement, layout, and look & feel.

+ + + +
Goal Level: summary_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: The Portal Administrator wants to modify an existing portal
Preconditions: + +

+ + + +
Basic Path: + +

+ +

    + +
  1. The Portal Administrator navigates to the configuration + page for the portal by selecting the link 'Configure Portal'.
  2. + +
  3. She chooses the 'Basic' tab to modify: +
  4. + +
  5. She chooses the 'Layout' tab to: +
  6. + +
+ +

+ + + +
Postconditions: + +

+ + + +
Succesful End Conditions: + +

The basic + attributes of the portal are updated.

+ + + +
Alternate Paths: + +

+ + + +
Exception Paths: + +

+ + + +
Failure End Conditions: + +

+ + + +
Sample Narrative: + +

+ + + +
Open Issues: + +

+ +
+ + + + +
Iteration: + Filled + +
Status: ready_for_review
+

+ by Eric Lorenzo +

+ Last Modified: 2003/02/28 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00011.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00011.xml.html new file mode 100644 index 000000000..0a2995e7e --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00011.xml.html @@ -0,0 +1,112 @@ + + + + + Use Case 00011:Modify Portal Mission + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00011:Modify Portal Mission

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: A Portal Administrator wishes to change the mission statement for a portal
Preconditions:
Basic Path: + +
    +
  1. Starting at the Portal, A PA navigates to the Portal Configuration page by clicking the "Configure Portal" link
  2. +
  3. On the Portal Configuration page, the PA selects the 'basic' tab.
  4. +
  5. The PA then edits the mission statement for the Portal, and clicks save.
  6. +
+

+ + +
Postconditions:
Succesful End Conditions: + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration: + Filled + +
Status: ready_for_review
+

+ by Jim Parsons +

+ Last Modified: 2003/02/28 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00012.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00012.xml.html new file mode 100644 index 000000000..5726c3942 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00012.xml.html @@ -0,0 +1,172 @@ + + + + + Use Case 00012:Modify Portal Name + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00012:Modify Portal Name

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ A method for changing the name of an existing Portal. +

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: The PA desires to change the name of an existing Portal
Preconditions: + +

+ + + +
Basic Path: + +


+

    +
  1. Starting at the Portal, A PA navigates to the Portal Configuration page by clicking the "Configure Portal" link
  2. +
  3. On the Portal Configuration page, the PA selects the 'basic' tab.
  4. +
  5. The PA then enters the new name for the Portal, and clicks save.
  6. +
+

+ + + +
Postconditions: + +

+ + + +
Succesful End Conditions: + +

+ The name of the Portal is changed to the desired name. +

+ + + +
Alternate Paths: + +

+ + + +
Exception Paths: + +

+ + + +
Failure End Conditions: + +

+ + + +
Sample Narrative: + +

+ + + +
Open Issues: + + ince changing the URL of a portal is not available yet, will having the Portal name and the URL being wildly different confuse + the user? + + + + +
Iteration: + Focused + +
Status: ready_for_review
+

+ by Jim Parsons +

+ Last Modified: 2003/02/28 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00014.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00014.xml.html new file mode 100644 index 000000000..ff1d2803b --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00014.xml.html @@ -0,0 +1,195 @@ + + + + + Use Case 00014:Modify Portal URL Stub + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00014:Modify Portal URL Stub

+

+

Release Target: 2.1

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ A method is needed for a Portal Administrator to change the final portion of a portal URL that refers to the Portal location + on the Site Map. +

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: A PA for a Portal desires to change the section of a portal URL that refers specifically to this Portal's location on the + Site Map +
Preconditions: + +

+ +

+ + + +
Basic Path: + +


+

    +
  1. Within the Portal, the PA clicks on the link for Portal Configuration
  2. +
  3. The PA locates a Text Field on the page named URL Stub. The current stub name is pre-loaded within this field
  4. +
  5. The PA changes the value within this field to the name he or she prefers
  6. +
  7. The PA clicks on the "Save Configuration" button
  8. +
  9. The PA is returned to the Portal Configuration page
  10. +
+

+ + + +
Postconditions: + +

+

+ + + +
Succesful End Conditions: + +

+ The URL Stub name is successfully changed +

+ + + +
Alternate Paths: + +

+ +

+ + + +
Exception Paths: + +

+ Two possible exceptions to this Use Case are: +

    +
  • The URL Stub text field is left blank. In this case, the config page is redisplayed with the error explained in red + text next to the text field, such as "Required Field"
  • +
  • The URL Stub name entered has whitespace or unacceptable characters in it.If so, the config page is redisplayed with + a message in red text explaining the nature of the error, such as "unacceptable character '!'
  • +
+

+ + + +
Failure End Conditions: + +

+ +

+ + + +
Sample Narrative: + +

+

+ + + +
Open Issues: + +


+

+ + +

+ + + +
Iteration: + Facade + +
Status: not_started
+

+ by Jim Parsons +

+ Last Modified: 2001/10/31 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00015.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00015.xml.html new file mode 100644 index 000000000..09628dc9e --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00015.xml.html @@ -0,0 +1,185 @@ + + + + + Use Case 00015:Move Portal + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00015:Move Portal

+

+

Release Target: 2.1

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

A Global Portal + Administrator may move around portals within the portal + hierarchy.

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: The Portal Administrator wants to move around parts of the portal hierarchy
Preconditions: + +

+ + + +
Basic Path: + +

+ +

    + +
  1. The Portal Administrator navigates to "Move Portal" + interface under global portal management.
  2. + +
  3. She selects the portal to be moved. (The toplevel portal may not be selected.)
  4. + +
  5. She selects the new parent for the portal being moved.
  6. + +
  7. She reviews the planned change.
  8. + +
  9. She confirms the change.
  10. + +
+ +

+ + + +
Postconditions: + +

+ + + +
Succesful End Conditions: + +

The first + portal specified is moved in the hierarchy so that it's parent is + the second portal specified. The children of the moved portal + move with it.

+ + + +
Alternate Paths: + +

+ + + +
Exception Paths: + +

+ + + +
Failure End Conditions: + +

+ + + +
Sample Narrative: + +

+ + + +
Open Issues: + +

+ +
+ + + + +
Iteration: + Facade + +
Status: not_started
+

+ by Eric Lorenzo +

+ Last Modified: 2001/10/31 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00030.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00030.xml.html new file mode 100644 index 000000000..e8105621a --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00030.xml.html @@ -0,0 +1,181 @@ + + + + + Use Case 00030:Navigate to a related portal + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00030:Navigate to a related portal

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

A Portal Participant + sees and can navigate to portals related to the one currently under + scrutiny. A related portal may be merely associated or it may + additionally be a "child" portal to the current portal.

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: The user wishes to move from the current portal to another relevant portal
Preconditions: + +

+

    +
  1. The current portal must have at least one portal in relation to it, + and that portal must be accessible by the user.
  2. +
  3. The current portal must have a Navigator Portlet installed.
  4. +
+

+ + + +
Basic Path: + +

+ +

    +
  1. The user visits the portal home page.
  2. + +
  3. The system displays a list of related portals that the user + has access to. If a related portal is a child of the current + portal, it is marked as such.
  4. + +
  5. The user selects one of the portals and navigates to it.
  6. + +
  7. The chosen portal appears in place of the old one. +
+ +

+ + + +
Postconditions: + +

+ + + +
Succesful End Conditions: + +

The user + reaches a related portal.

+ + + +
Alternate Paths: + +

+ + + +
Exception Paths: + +

+ + + +
Failure End Conditions: + +

+ + + +
Sample Narrative: + +

+ + + +
Open Issues: + +

+ + + +
Iteration:
Status: ready_for_review
+

+ by Justin Ross +

+ Last Modified: 2003/02/28 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00033.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00033.xml.html new file mode 100644 index 000000000..47b74c2db --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00033.xml.html @@ -0,0 +1,141 @@ + + + + + Use Case 00033:Add another Portal as a Related Portal + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00033:Add another Portal as a Related Portal

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ A Portal Administrator (PA) wishes to add a reference to his or her Portal to a Related Portal. +

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: A Portal Administrator wishes to add a reference to another portal as a Related APortal
Preconditions: + +

+ It is a necessary pre-condition for this Use Case, that at least one other Portal has granted "Related Portal" access. +

+ + + +
Basic Path: + +


+

    +
  1. The PA clicks on the Configure Portal link
  2. +
  3. The PA then the Related Portals Tab
  4. +
  5. The PA is presented with a list of Portals on the system that have granted access as a related portal to the PA's portal + group. Note: Those Portals that are already listed as related Portals are listed, but grayed out.
  6. +
  7. The PA selects a Portal from the list
  8. +
  9. The PA then clicks the Add Related Portal button on this configuration page
  10. +
  11. The PA is returned to the Portal Tab Configuration page. +
+

+ + + +
Postconditions:
Succesful End Conditions: + +

+ The new related Portal appears within the Related Portals portlet. +

+ + + + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration: + Focused + +
Status: ready_for_review
+

+ by Jim Parsons +

+ Last Modified: 2001/10/30 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00050.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00050.xml.html new file mode 100644 index 000000000..fee21ab0d --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00050.xml.html @@ -0,0 +1,190 @@ + + + + + Use Case 00050:Browse portal participants + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00050:Browse portal participants

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

A Portal Participant + wishes to browse through a listing of all participants in the + portal.

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: A Portal Participant wishes to browse through a listing of all participants in the portal
Preconditions: + + A participants portlet must be installed in the Portal. + + +
Basic Path: + +


+

    +
  1. The Portal Participant navigates to the "Participants" + listing screen for the portal.
  2. +
  3. The participant is presented with a listing of all participants + in the portal and certain frequently-needed information. If + the number of participants exceeds some threshold, the list will + be broken up into multiple pages, with links for quick access to + partcipants whose names begin with particular letters of the + alphabet.
  4. +
  5. Each entry in the provided list will include a link to drill + down to the "One Participant" view. See PSRV-00052 ("View a single participant's + activities and roles within a portal") for a description of + this view.
  6. +
+

+ + + +
Postconditions: + +

+

+ + + +
Succesful End Conditions: + +

The user is + able to view listings of participants within the portal, and drill + down to detailed views of individual participants.

+ + + + +
Alternate Paths: + +

+ +

+ + + +
Exception Paths: + +

+ +

+ + + +
Failure End Conditions: + +

+ +

+ + + +
Sample Narrative: + +

+

+ + + +
Open Issues: + +


+

+ + + + +
Iteration: + Focused + +
Status: ready_for_review
+

+ by Eric Lorenzo +

+ Last Modified: 2001/11/01 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00051.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00051.xml.html new file mode 100644 index 000000000..5fb3c33a0 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00051.xml.html @@ -0,0 +1,183 @@ + + + + + Use Case 00051:Search for a portal participant + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00051:Search for a portal participant

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

A Portal Participant + wants to find participants in a portal meeting certain + criteria.

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: A Portal Participant wants to find participants within a portal meeting certain criteria
Preconditions: + +

+

+ + + +
Basic Path: + +


+

    +
  1. The Participant navigates to the "People" tab in the + Configure Portal area, and clicks on the "search" link.
  2. +
  3. The Participant specifies search criteria, which may include + participant name and role assignments.
  4. +
  5. The Participant is presented with a set of matching + participants. This listing format shall be the same as that + described in as the browse listing described in PSRV-00050 ("Browse Portal + Participants").
  6. +
+

+ + + +
Postconditions: + +

+

+ + + +
Succesful End Conditions: + +

+ The Participant finds participants matching the specified criteria. +

+ + + + +
Alternate Paths: + +

+

+ + + +
Exception Paths: + +

+

+ + + +
Failure End Conditions: + +

+

+ + + +
Sample Narrative: + +

+

+ + + +
Open Issues: + + The complexity of available search parameters is an open issue. + + + +
Iteration: + Focused + +
Status: in_progress
+

+ by Eric Lorenzo +

+ Last Modified: 2003/02/28 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00052.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00052.xml.html new file mode 100644 index 000000000..c29a1e6ae --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00052.xml.html @@ -0,0 +1,200 @@ + + + + + Use Case 00052:View/Administer a single participant + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00052:View/Administer a single participant

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

A Portal Participant + wishes to view various information about a specific portal + participant. A Portal Administrator may also want to perform + various other administrative tasks on a participant.

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: A Portal Participant wishes to view various information about a specific portal participant, or a Portal Administrator wishes + to perform administrative actions related to a specific participant +
Preconditions: + +

+ +

+ + + +
Basic Path: + +


+

    + +
  1. The Portal Participant locates the participant they are + interested in via PSRV-00051:Search for a portal participant.
  2. +
  3. The Participant clicks on a "view" link next to the name of the + participant of interest.
  4. +
  5. The resulting view page presents the Participant with a history + of the selected participant as well as their other activities, + and also various other information specific to the selected participant, + such as their role assignments in the portal. In addition, this view + will present data on the user that is not associated with any + portal, such as position in the organization structure and + contact information.
  6. +
+

+ + + +
Postconditions: + +

+

+ + + +
Succesful End Conditions: + +

The user is + able to view listings of participants within the portal, and drill + down to detailed views of individual participants.

+ + + + +
Alternate Paths: + +

+

    +
  • When viewed by an Administrator, this page will also serve as + a participant administration page: UI will be provided for + adjusting their role assignments (See PSRV-00065), for + removing the participant from the portal (See PSRV-00056), and for any other + administrative tasks that are identified.

    +
  • +
+ + + +
Exception Paths: + +

+ +

+ + + +
Failure End Conditions: + +

+ +

+ + + + + +
Sample Narrative: + +

+

+ + + +
Open Issues: + None + +
Iteration: + Focused + +
Status: in_progress
+

+ by Eric Lorenzo +

+ Last Modified: 2001/11/01 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00055.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00055.xml.html new file mode 100644 index 000000000..97a8ef881 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00055.xml.html @@ -0,0 +1,200 @@ + + + + + Use Case 00055:Add a portal participant + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00055:Add a portal participant

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

A Portal Administrator + wants to add a participant to a portal.

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: A Portal Administrator wishes to add a new participant to a portal
Preconditions: + +

+

+ + + +
Basic Path: + +


+

    + +
  1. The Portal Administrator navigates to the "Participants" + screen for the portal to which participants are to be + added.
  2. +
  3. The Administrator then clicks on the "Add New Participant" link.
  4. +
  5. The Administrator then types in a name or email address to search for + the users and groups that might be added.
  6. +
  7. A list of matches is returned. The Administrator clicks on the + name of the party to be made a participant.
  8. +
  9. The Administrator selects the role(s) the participant is to play + in the portal.
  10. +
+

+ + + +
Postconditions: + +

+

+ + + +
Succesful End Conditions: + +

+ The selected parties are made participants in the portal, with the + specified roles. +

+ + + + +
Alternate Paths: + +

+

+ + + +
Exception Paths: + +

+

+ + + +
Failure End Conditions: + +

+

+ + + +
Sample Narrative: + +

+

+ + + +
Open Issues: + +


+

    +
  • Should people who are already participants show up in the search + results? Leaving them out could prove annoying in situations + where the Administrator does not know that the party they're + looking for is already a participant. Including existing + participants, with some sort of flag indicating that they're + already participants (and linking to the "View/Administer a single + participant" page (PSRV-00052) may + make more sense.
  • +
+

+ + + + + + + +
Iteration: + Focused + +
Status: in_progress
+

+ by Eric Lorenzo +

+ Last Modified: 2001/11/01 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00056.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00056.xml.html new file mode 100644 index 000000000..ff7f1b721 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00056.xml.html @@ -0,0 +1,193 @@ + + + + + Use Case 00056:Remove a portal participant + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00056:Remove a portal participant

+

+

Release Target: 2.1

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

A Portal Administrator + wants to remove a participant from a portal.

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: A Portal Administrator wishes to remove an existing participant from a portal
Preconditions: + +

+ +

+ + + +
Basic Path: + +


+

    +
  1. The Portal Administrator navigates to the "View One + Participant" page, using PSRV-00052.
  2. +
  3. The Administrator clicks on a "Remove this participant" link.
  4. +
  5. The Administrator is returned to the portal's "Participants" + page.
  6. +
+

+ + + +
Postconditions: + +

+

+ + + +
Succesful End Conditions: + +

+ The selected party is removed as a participant of the portal. +

+ + + + +
Alternate Paths: + +

+ +

+ + + +
Exception Paths: + +

+

    +
  • If removing a participant will leave some responsibility/role + unassigned, the administrator should be presented with a + confirmation screen that lists these responsibilities and asks the + administrator to confirm the removal decision. This screen may + also provide shortcuts for re-assigning those responsibilities to + new roles or individuals.
  • +
+

+ + + +
Failure End Conditions: + +

+ +

+ + + +
Sample Narrative: + +

+

+ + + +
Open Issues: + + What happens if a participant is removed who has roles? Particpants with roles should not be deleted, but deactivated. If + an attempt is made to delete them, perhaps the system should deny this action until all roles have been disassociated with + that participant. + + + + +
Iteration: + Filled. + +
Status: in_progress
+

+ by Eric Lorenzo +

+ Last Modified: 2001/11/01 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00057.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00057.xml.html new file mode 100644 index 000000000..6314a5bc5 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00057.xml.html @@ -0,0 +1,103 @@ + + + + + Use Case 00057:Invite a participant to a portal + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00057:Invite a participant to a portal

+

+

Release Target: 2.1

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: The event that gets the use case started
Preconditions:
Basic Path: + Basic path for the use case + +
Postconditions:
Succesful End Conditions: + Description of success from the user's point of view. + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration:
Status: not_started
+

+ by Author's Name +

+ Last Modified: 2001/12/06 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00065.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00065.xml.html new file mode 100644 index 000000000..0a197b29d --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00065.xml.html @@ -0,0 +1,186 @@ + + + + + Use Case 00065:Modify a participant's role assignments + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00065:Modify a participant's role assignments

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

A Portal Administrator + wants to modify a participant's role assignments.

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: A Portal Administrator wants to modify a participant's role assignments
Preconditions: + +

+

+ + + +
Basic Path: + +


+

    +
  1. The Portal Administrator navigates to the "View One + Participant" page, using PSRV-00052.
  2. +
  3. The Administrator is provided with a set of checkboxes for + the roles available in the current portal. Boxes for the roles + that the participant already possesses are already checked.
  4. +
  5. The Administrator checks and unchecks boxes to change role + assignments.
  6. +
  7. The Administrator clicks an "Update Role Assignments" button to + confirm the changes.
  8. +
+

+ + + +
Postconditions: + +

+

+ + + +
Succesful End Conditions: + +

+ The desired role assignment changes are made. +

+ + + + +
Alternate Paths: + +

+

+ + + +
Exception Paths: + +

+

+ + + +
Failure End Conditions: + +

+

+ + + +
Sample Narrative: + +

+

+ + + +
Open Issues: + +


+

+ + + + + +
Iteration: + Focused + +
Status: in_progress
+

+ by Eric Lorenzo +

+ Last Modified: 2001/11/01 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00100.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00100.xml.html new file mode 100644 index 000000000..c2f03e48d --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00100.xml.html @@ -0,0 +1,159 @@ + + + + + Use Case 00100:Add a Tab to a Portal + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00100:Add a Tab to a Portal

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ The Portal administrator should be able to create and save tabs within a portal. +

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: A portal administrator has decided that an additional tab on a particular portal is desirable for organizational purposes
Preconditions: + +

+ Of course, this Use Case relies on the existence of a Portal in the first place. Every new portal is built with a default + tab. + This tab is named "Main". The name of this tab, or any other tab can be + changed within the tab configuration page (See PSRV-00110:Configure a Portal Tab Use Case). +

+ + + + +
Basic Path: + +


+

    +
  1. The PA visits the Portal Home page.
  2. +
  3. The PA selects the Configure Portal link
  4. +
  5. The PA then selects the link for 'Create a New Portal Tab'
  6. +
  7. The PA then enters a name for the new Portal Tab(this is a required field)
  8. +
  9. The PA then clicks the Create Tab button
  10. +
  11. The PA is then taken to the Configuration page for the new Tab
  12. +
+

+ + + +
Postconditions:
Succesful End Conditions: + +

+ The new tab is created, and available for customization. +

+ + + +
Alternate Paths: + + + +
Exception Paths:
Failure End Conditions:
Sample Narrative: + +

+

+ + + +
Open Issues: + + + + +
Iteration: + Finished + +
Status: ready_for_review
+

+ by Jim Parsons +

+ Last Modified: 2003/02/28 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00110.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00110.xml.html new file mode 100644 index 000000000..b314c2dab --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00110.xml.html @@ -0,0 +1,195 @@ + + + + + Use Case 00110:Configure A Portal Tab + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00110:Configure A Portal Tab

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ Tabs are the principle organizational mechanism for restricting view clutter and focusing Portal data and function. This Use + Case describes the procedure to follow when a modification to a Tab is desired. +

+ + + +
Goal Level: summary_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: A PA desires to modify the configuration for a Portal Tab
Preconditions: + +

+ +

+ + + +
Basic Path: + +


+

    +
  1. Starting at the Portal, he PA selects the "Configure Portal" link.
  2. +
  3. The 'Layout' tab is chosen next.
  4. +
  5. At the Configure Portal page, the PA is presented a list of all Tabs currently residing within the Portal. The PA selects + a Tab to configure.
  6. +
  7. The PA makes the desired configuration changes and then clicks the "Save Configuration" button. Configuration changes + available include: +
  8. +
+

+ + + +
Postconditions: + +

+

+ + + +
Succesful End Conditions: + +

+ The desired config changes are made and saved. +

+ + + +
Alternate Paths: + +

+ +

+ + + +
Exception Paths: + +

+ +

+ + + +
Failure End Conditions: + +

+ +

+ + + +
Sample Narrative: + +

+

+ + + +
Open Issues: + +


+

+ + + + +
Iteration: + Focused + +
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2003/02/28 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00120.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00120.xml.html new file mode 100644 index 000000000..f464783e7 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00120.xml.html @@ -0,0 +1,144 @@ + + + + + Use Case 00120:Delete a Portal Tab + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00120:Delete a Portal Tab

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ A Portal Administrator (PA) should have a method available for deleting an existing Portal Tab. +

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: The Portal contains more than the Main Tab, and a Portal Tab exists that a PA wishes to remove
Preconditions: + +

+ It is necessary that the Portal contain more than the "Main" tab at the start of this Use Case. If a Portal only contains + a "Main" tab, the Portal Configuration page will not offer the option to remove the "Main" Tab. +

+ + + + + + +
Basic Path: + +


+

    +
  1. A PA selects the 'Configure Portal' link.
  2. +
  3. The PA scans the list of Portal Tabs associated with that Portal
  4. +
  5. The PA locates the tab he or she wishes to remove, and selects the 'Delete' link next to it.
  6. +
  7. A confirmation dialogue appears asking the PA to choose from two choices: +
    • "Proceed with Tab Deletion"
    • Or
    • Cancle
    +
  8. The PA is returned to the "Configure Portal" page. If "Proceed with Tab Deletion" was selected above, then the deleted + tab no longer appears in the list of tabs associated with the Portal
  9. +
+

+ + + +
Postconditions:
Succesful End Conditions: + +

+ The tab that the PA desires to delete is removed. +

+ + + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration: + Filled + +
Status: ready_for_review
+

+ by Jim Parsons +

+ Last Modified: 2001/10/30 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00140.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00140.xml.html new file mode 100644 index 000000000..7b05c6c13 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00140.xml.html @@ -0,0 +1,134 @@ + + + + + Use Case 00140:Change Name of Existing Portal Tab + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00140:Change Name of Existing Portal Tab

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ This Use Case describes the procedure for changing the name of an existing Portal tab. +

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: a A PA is unhappy with the name of one of the Portal Tabs, and wishes to modify the name
Preconditions:
Basic Path: + +


+

    +
  1. The PA navigates to the Portal and selects the "Configure Portal" link.
  2. +
  3. The PA is presented with a list of all tabs associated with this Portal
  4. +
  5. The PA selects the tab that he wishes to rename.
  6. +
  7. The PA selects the "Rename Tab" link.
  8. +
  9. A small form is presented to the PA with a field for the tabs name.
  10. +
  11. The PA changes the name within the Text Field
  12. +
  13. The PA then clicks the "Save Configuration" button.
  14. +
+

+ + + +
Postconditions:
Succesful End Conditions: + +

+ The name of the Portal Tab is changed successfully. +

+ + + + + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration: + Focused + +
Status: ready_for_review
+

+ by Jim Parsons +

+ Last Modified: 2001/10/30 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00150.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00150.xml.html new file mode 100644 index 000000000..612741a12 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00150.xml.html @@ -0,0 +1,112 @@ + + + + + Use Case 00150:Reorder Portal Tabs + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00150:Reorder Portal Tabs

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: PA desires to change position of a Portal Tab relative to the others.
Preconditions:
Basic Path: + +
    +
  1. The Portal Administrator selects the 'Configure Portal' link.
  2. +
  3. The PA then selects the portal tab from the list that he wishes to reposition.
  4. +
  5. When selected, repositioning arrows/links appear next to the tab.
  6. +
  7. The PA shifts the Tab right or left, as desired.
  8. +
+ + +
Postconditions:
Succesful End Conditions: + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration: + Finished + +
Status: ready_for_review
+

+ by Jim Parsons +

+ Last Modified: 2003/02/28 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00200.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00200.xml.html new file mode 100644 index 000000000..ca90cfae5 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00200.xml.html @@ -0,0 +1,187 @@ + + + + + Use Case 00200:Add a Portlet to a Portal Tab + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00200:Add a Portlet to a Portal Tab

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ This use case describes the series of events necessary to adding a portlet to an already existing Portal Tab +

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: A PA is interested in adding a Portlet to a Tab within a Portal
Preconditions: + +

+ +

+ + + +
Basic Path: + +


+

    +
  1. Beginning at the Portal, a PA clicks the "Configure Portal" + link
  2. +
  3. On the Configure Portal page, the PA is presented with a list of all Tabs that currently reside within the Portal.
  4. + +
  5. The PA chooses the Tab he or she would like to supplement with a new Portlet.
  6. +
  7. The PA then clicks the "Add/Remove" portlets. This launches a drop down box listing all portlets available on the system. +
  8. +
  9. The PA check the Portlet he wishes to add.
  10. +
+

+ + + +
Postconditions: + +

+

+ + + +
Succesful End Conditions: + +

+ The desired Portlets are added to the Portal +

+ + + +
Alternate Paths: + +

+ +

+ + + +
Exception Paths: + +

+ +

+ + + +
Failure End Conditions: + +

+ +

+ + + +
Sample Narrative: + +

+

+ + + +
Open Issues: + +


+

+ + + + +
Iteration: + Focused + +
Status: ready_for_review
+

+ by Jim Parsons +

+ Last Modified: 2001/11/01 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00210.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00210.xml.html new file mode 100644 index 000000000..d76a74399 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00210.xml.html @@ -0,0 +1,188 @@ + + + + + Use Case 00210:Delete a Portlet from a Portal Tab + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00210:Delete a Portlet from a Portal Tab

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ This use case describes the series of events necessary to delete a portlet in an already existing Portal Tab +

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: A PA is interested in deleting a Portlet from a Tab within a Portal
Preconditions: + +

+ +

+ + + +
Basic Path: + +


+

    +
  1. Beginning at the Portal, a PA clicks the "Configure Portal" + link
  2. +
  3. On the Configure Portal page, the PA is presented with a list of all Tabs that currently reside within the Portal. Next + to the name of each Tab, is a link saying "configure" and a link saying "delete".
  4. +
  5. The PA chooses the Tab he or she would like to delete a Portlet from, and chooses the "Configure" link for that Tab
  6. +
  7. The Tab configuration page presents the PA with an Option to "Add/Remove Portlets". The PA selects this link
  8. +
  9. On the Add/Remove Portlets page, all available Portlets appear as a checkable list, partitioned conveniently by Package + Type. Portlets already included within this Tab are pre-checked, while unused available Portlets appear as unchecked
  10. +
  11. The PA unchecks those Portlets he or she wishes to remove, and then clicks the "Save Configuration"button
  12. +
  13. The PA is returned to the Tab configuration Page
  14. +
+

+ + + +
Postconditions: + +

+

+ + + +
Succesful End Conditions: + +

+ The desired Portlets are removed from the Portal +

+ + + +
Alternate Paths: + +

+ +

+ + + +
Exception Paths: + +

+ +

+ + + +
Failure End Conditions: + +

+ +

+ + + +
Sample Narrative: + +

+

+ + + +
Open Issues: + +


+

+ + + +
Iteration: + Focused + +
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2001/11/02 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00220.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00220.xml.html new file mode 100644 index 000000000..ff0b45d2b --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00220.xml.html @@ -0,0 +1,103 @@ + + + + + Use Case 00220:Change the Layout for a Portal Tab + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00220:Change the Layout for a Portal Tab

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: The event that gets the use case started
Preconditions:
Basic Path: + Basic path for the use case + +
Postconditions:
Succesful End Conditions: + Description of success from the user's point of view. + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration:
Status: not_started
+

+ by Author's Name +

+ Last Modified: 2001/12/06 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00230.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00230.xml.html new file mode 100644 index 000000000..6b3291fe4 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00230.xml.html @@ -0,0 +1,103 @@ + + + + + Use Case 00230:Move a Portlet to a New Position Within a Portal Tab + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00230:Move a Portlet to a New Position Within a Portal Tab

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: The event that gets the use case started
Preconditions:
Basic Path: + Basic path for the use case + +
Postconditions:
Succesful End Conditions: + Description of success from the user's point of view. + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration:
Status: not_started
+

+ by Author's Name +

+ Last Modified: 2001/12/06 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00240.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00240.xml.html new file mode 100644 index 000000000..f5c097ff8 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00240.xml.html @@ -0,0 +1,182 @@ + + + + + Use Case 00240:Configure a Portlet + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00240:Configure a Portlet

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ A Portal Administrator wishes to customize a portlet that currently resides + within a Tab in the Portal. +

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: A PA wishes to alter the presentation or a Portlet within a Portal
Preconditions: + +

+ +

+ + + +
Basic Path: + +


+

    +
  1. Starting at the Portal, a PA clicks the Configure Portal link
  2. +
+ +

+ + + +
Postconditions: + +

+

+ + + +
Succesful End Conditions: + +

+

+ + + +
Alternate Paths: + +

+ +

+ + + +
Exception Paths: + +

+ +

+ + + +
Failure End Conditions: + +

+ +

+ + + +
Sample Narrative: + +

+

+ + + +
Open Issues: + +


+

+ + + + + +
Iteration: + Filled + +
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2001/11/02 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00310.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00310.xml.html new file mode 100644 index 000000000..22f387574 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00310.xml.html @@ -0,0 +1,103 @@ + + + + + Use Case 00310:Add an Application to a Portal + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00310:Add an Application to a Portal

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: The event that gets the use case started
Preconditions:
Basic Path: + Basic path for the use case + +
Postconditions:
Succesful End Conditions: + Description of success from the user's point of view. + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration:
Status: not_started
+

+ by Author's Name +

+ Last Modified: 2001/12/06 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00320.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00320.xml.html new file mode 100644 index 000000000..96533f152 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00320.xml.html @@ -0,0 +1,103 @@ + + + + + Use Case 00320:Remove an Application from a Portal + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00320:Remove an Application from a Portal

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: The event that gets the use case started
Preconditions:
Basic Path: + Basic path for the use case + +
Postconditions:
Succesful End Conditions: + Description of success from the user's point of view. + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration:
Status: not_started
+

+ by Author's Name +

+ Last Modified: 2001/12/06 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00330.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00330.xml.html new file mode 100644 index 000000000..4885af657 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00330.xml.html @@ -0,0 +1,103 @@ + + + + + Use Case 00330:Navigate to Applications Within a Portal + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00330:Navigate to Applications Within a Portal

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: The event that gets the use case started
Preconditions:
Basic Path: + Basic path for the use case + +
Postconditions:
Succesful End Conditions: + Description of success from the user's point of view. + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration:
Status: not_started
+

+ by Author's Name +

+ Last Modified: 2001/12/06 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00340.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00340.xml.html new file mode 100644 index 000000000..922798eb4 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00340.xml.html @@ -0,0 +1,103 @@ + + + + + Use Case 00340:Configure an Application Instance + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00340:Configure an Application Instance

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: The event that gets the use case started
Preconditions:
Basic Path: + Basic path for the use case + +
Postconditions:
Succesful End Conditions: + Description of success from the user's point of view. + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration:
Status: not_started
+

+ by Author's Name +

+ Last Modified: 2001/12/06 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00400.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00400.xml.html new file mode 100644 index 000000000..88d4e5cc5 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00400.xml.html @@ -0,0 +1,103 @@ + + + + + Use Case 00400:Create a Related Portal reference between two portals + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00400:Create a Related Portal reference between two portals

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: The event that gets the use case started
Preconditions:
Basic Path: + Basic path for the use case + +
Postconditions:
Succesful End Conditions: + Description of success from the user's point of view. + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration:
Status: not_started
+

+ by Author's Name +

+ Last Modified: 2001/12/06 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00405.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00405.xml.html new file mode 100644 index 000000000..6448ef1b1 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00405.xml.html @@ -0,0 +1,103 @@ + + + + + Use Case 00405:Remove a Related Portal reference between two portals + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00405:Remove a Related Portal reference between two portals

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: The event that gets the use case started
Preconditions:
Basic Path: + Basic path for the use case + +
Postconditions:
Succesful End Conditions: + Description of success from the user's point of view. + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration:
Status: not_started
+

+ by Author's Name +

+ Last Modified: 2001/12/06 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00410.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00410.xml.html new file mode 100644 index 000000000..7013ffa8c --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00410.xml.html @@ -0,0 +1,178 @@ + + + + + Use Case 00410:Navigate to a related portal + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00410:Navigate to a related portal

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

A Portal Participant + sees and can navigate to portals related to the one currently under + scrutiny. A related portal may be merely associated or it may + additionally be a "child" portal to the current portal.

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: The user wishes to move from the current portal to another relevant portal
Preconditions: + +

The current portal + must have at least one portal in relation to it, and that portal + must be accessible by the user.

+ + + +
Basic Path: + +

+ +

    +
  1. The user visits the portal home page.
  2. + +
  3. The system displays a list of related portals that the user + has access to. If a related portal is a child of the current + portal, it is marked as such.
  4. + +
  5. The user selects one of the portals and navigates to it.
  6. + +
  7. The chosen portal appears in place of the old one, and the + system provides a way to navigate back.
  8. +
+ +

+ + + +
Postconditions: + +

+ + + +
Succesful End Conditions: + +

The user + reaches a related portal.

+ + + +
Alternate Paths: + +

+ + + +
Exception Paths: + +

+ + + +
Failure End Conditions: + +

+ + + +
Sample Narrative: + +

+ + + +
Open Issues: + +

+ + + +
Iteration:
Status: in_progress
+

+ by Justin Ross +

+ Last Modified: 2001/10/30 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00500.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00500.xml.html new file mode 100644 index 000000000..64f982357 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00500.xml.html @@ -0,0 +1,198 @@ + + + + + Use Case 00500:Archive a Portal + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00500:Archive a Portal

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ A Portal set up for a particular project team is archived when the project is completed. +

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: An administrator of a Portal wishes to unlink it from he sitemap and store it in its archived state
Preconditions: + +

+ +

+ + + +
Basic Path: + +


+ +

    +
  1. The administrator visits the Portal homepage.
  2. +
  3. The administrator clicks on the "Configure Portal" link.
  4. +
  5. The administrator chooses the "Archive Portal" link.
  6. +
  7. The administrator is prompted to enter any comments he or she wishes to associate with the archived Portal.
  8. +
  9. A confirmation message and button is displayed asking if the administrator is sure that he or she wishes to unlink the + Portal from the active sitemap to be stored.
  10. +
  11. A "Successfully Archived" page is displayed.
  12. +
+

+ + + +
Postconditions: + +

+ In archived state, a Portal is available to the non-administrative users as a Read-Only Portal. Administrators can still access + the configuration page for the archived Portal, and modify the user access list for the Portal. +
+
+ In addition, an administrator can "un-archive" a Portal if desired, but this is a separate use case! + +

+ + + +
Succesful End Conditions: + +

+ The Portal is successfully archived below the "/archived-portals" node, and is accessible by Portal group members in Read + Only mode. + +

+ + + +
Alternate Paths: + +

+ +

+ + + +
Exception Paths: + +

+ +

+ + + +
Failure End Conditions: + +

+ +

+ + + +
Sample Narrative: + +

+ + +

+ + + +
Open Issues: + +


+

+ + + + + +
Iteration: + Filled. + +
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2001/10/31 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00501.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00501.xml.html new file mode 100644 index 000000000..badfa8ce4 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00501.xml.html @@ -0,0 +1,103 @@ + + + + + Use Case 00501:Un-Archive a Portal + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00501:Un-Archive a Portal

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: The event that gets the use case started
Preconditions:
Basic Path: + Basic path for the use case + +
Postconditions:
Succesful End Conditions: + Description of success from the user's point of view. + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration:
Status: not_started
+

+ by Author's Name +

+ Last Modified: 2001/12/06 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00610.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00610.xml.html new file mode 100644 index 000000000..5163f242e --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00610.xml.html @@ -0,0 +1,103 @@ + + + + + Use Case 00610:Navigate to a Personal Portal + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00610:Navigate to a Personal Portal

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: A user wishes to navigate to a personal portal.
Preconditions:
Basic Path: + Basic path for the use case + +
Postconditions:
Succesful End Conditions: + Description of success from the user's point of view. + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration:
Status: ready_for_review
+

+ by Jim Parsons +

+ Last Modified: 2003/02/28 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00710.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00710.xml.html new file mode 100644 index 000000000..bbae96158 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00710.xml.html @@ -0,0 +1,136 @@ + + + + + Use Case 00710:View Help for the Current System Page + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00710:View Help for the Current System Page

+

+

Release Target: 2.1

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ + This is a subfunction use case for the View Help summary use case (PSRV-00010).

+ +

The Portal Participant can open a Help page for any page in the Armenta system.

+ +

From this page, the WP has access to the complete Help system.

+ + + +
Goal Level: subfunction
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: The WP wants to find information about the page currently displayed by Armenta
Preconditions: + +

The WP participant is viewing an Armenta page.

+ + + +
Basic Path: + +

+ +

+

    +
  1. The WP selects the action to view Help for the current page.
  2. +
  3. The system displays a Help page with procedures for using the current Armenta page.
  4. +
+

+ + + + +
Postconditions:
Succesful End Conditions: + +

The System simultaneously displays the necessary Help page and the page it documents. +

+ + + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration:
Status: ready_for_review
+

+ by Jay Talbot +

+ Last Modified: 2001/12/27 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00730.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00730.xml.html new file mode 100644 index 000000000..2c9d76fd4 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00730.xml.html @@ -0,0 +1,157 @@ + + + + + Use Case 00730:Navigate Help Using a Table of Contents + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00730:Navigate Help Using a Table of Contents

+

+

Release Target: 2.1

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ +

This is a subfunction use case for the View Help summary use case (PSRV-00710).

+ +

From any Help page, the Portal Participant can view Help information organized in a traditional table of contents format. + In addition, the WP can quickly move to the appropriate Help files from the table of contents.

+ + + +
Goal Level: subfunction
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: The WP wants to find Help information through a table of contents format
Preconditions: + +

The WP participant is viewing a Help page.

+ + + +
Basic Path: + +

+ +

+

    +
  1. The WP selects the action to view the Help table of contents page.
  2. +
  3. The system displays the Help table of contents page.
  4. +
  5. The WP chooses a Help topic to view.
  6. +
  7. The system displays the selected Help topic.
  8. +
+

+ + + +
Postconditions:
Succesful End Conditions: + +

The system simultaneously displays the original Armenta page and the Help page that was + requested from the Help table of contents page.

+ + + +
Alternate Paths:
Exception Paths: + +

None

+ + + +
Failure End Conditions: + +

None

+ + + + +
Sample Narrative:
Open Issues: + +

None +

+ + + + +
Iteration:
Status: ready_for_review
+

+ by Jay Talbot +

+ Last Modified: 2001/12/27 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00740.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00740.xml.html new file mode 100644 index 000000000..4e998c84a --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00740.xml.html @@ -0,0 +1,151 @@ + + + + + Use Case 00740:Search Help Using a Keyword + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00740:Search Help Using a Keyword

+

+

Release Target: 2.1

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ +

This is a subfunction use case for the View Help summary use case (PSRV-00710).

+ +

The Portal Participant can search the complete set of Help pages for those pages that have been associated with a specific + keyword.

+ +

Note: This capability does not have the priority to be completed for version 1. It will be included in version 2.

+ + + +
Goal Level: subfunction
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: The WP wants to find information that has been associated with one or more keywords
Preconditions: + +

The WP participant is viewing a Help page.

+ + + +
Basic Path: + +

+ +

+

    +
  1. The WP selects the action to search Help by keywords.
  2. +
  3. The system displays the Keyword Search page.
  4. +
  5. The WP enters a keyword or phrase and initiates the search.
  6. +
  7. The system displays a results page with the list of Help pages associated with the keyword.
  8. +
  9. The WP chooses a Help topic to view.
  10. +
  11. The system displays the selected Help topic.
  12. +
+

+ + + +
Postconditions:
Succesful End Conditions: + +

The system simultaneously displays the Armenta page from which Help was initiated and a + Help page that is associated with the keywords used for the search.

+ + + +
Alternate Paths: + +

+ +
    +
  1. If there are no Help pages associated with the keywords, the system displays a message indicating that there + are no Help pages associated with the specified keywords.
  2. +
+ + + +
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration:
Status: ready_for_review
+

+ by Jay Talbot +

+ Last Modified: 2001/12/27 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00750.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00750.xml.html new file mode 100644 index 000000000..8f52f9bda --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00750.xml.html @@ -0,0 +1,151 @@ + + + + + Use Case 00750:Search Help Using a Text String + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00750:Search Help Using a Text String

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ +

This is a subfunction use case for the View Help summary use case (PSRV-00710).

+ +

The Portal Participant can perform a full-text search of the complete set of Help pages to find those pages that include + a specified text string.

+ +

Note: This capability does not have the priority to be completed for version 1. It will be included in version 2.

+ + + +
Goal Level: subfunction
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: The WP wants to find any Help pages that include a specified text string
Preconditions: + +

The WP participant is viewing a Help page.

+ + + +
Basic Path: + +

+ +

+

    +
  1. The WP selects the action to do a full-text search of Help.
  2. +
  3. The system displays the Full Text Search page.
  4. +
  5. The WP enters a text string and initiates the search.
  6. +
  7. The system displays a results page with the list of Help pages that include the text string.
  8. +
  9. The WP chooses a Help topic to view.
  10. +
  11. The system displays the selected Help topic.
  12. +
+

+ + + +
Postconditions:
Succesful End Conditions: + +

The system simultaneously displays the Armenta page from which Help was initiated and a + Help page that includes the specified text sting.

+ + + +
Alternate Paths: + +

+ +
    +
  1. If no Help pages contain the text string, the system displays a message indicating that no Help pages contain + the text string.
  2. +
+ + + +
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration:
Status: ready_for_review
+

+ by Jay Talbot +

+ Last Modified: 2001/12/27 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00810.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00810.xml.html new file mode 100644 index 000000000..62e62432c --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00810.xml.html @@ -0,0 +1,199 @@ + + + + + Use Case 00810:Browsing Bookmarks within a Portal + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00810:Browsing Bookmarks within a Portal

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ This Use case is the Base Case for Bookmark functionality. General Bookmark + attributes and procedures are detailed here. +

+
+ The Collaborative Portal bookmarking model has one important distinction from browser bookmarking: In CW, Bookmarks can be + shared. In a Collaborative + Portal, the bookmark portlet is available for reading and use in most cases, by all participants. The ability to create a + bookmark and have it appear within the bookmark portlet for a particular portal, is controlled by write privelage on the bookmark + portlet.

+
+

+ A system user may have participant status in many different portals, including their own personal portal. When using a collaborative + portal or an application associated with a collaborative portal, the bookmark portlet + instanced by that portal only shows bookmarks associated with that portal. + When a user is at his or her own personal portal, the Bookmark portlet can be configured to show just personal bookmarks, + or import bookmarks as read/use only from collaborative portals that include the user as a member. +

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: A Portal participant is referred to a bookmark available within a portal
Preconditions: + +

+ This Use Case pre-supposes that the Bookmark portlet is present in the portal, and that it has at least one bookmark saved + there. +

+ + + +
Basic Path: + +


+

    +
  1. The portal participant chooses a bookmark entry from the bookmark portlet.
  2. +
  3. The participant is taken to that content item.
  4. +
+

+ + + +
Postconditions: + +

+

+ + + +
Succesful End Conditions: + +

+ The portal participant arrives at the desired content destination. +

+ + + +
Alternate Paths: + +

+ +

+ + + +
Exception Paths: + +

+ +

+ + + +
Failure End Conditions: + +

+ +

+ + + +
Sample Narrative: + +

+

+ + + +
Open Issues: + +


+

+ + + + + + +
Iteration: + Focused + +
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2001/11/21 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00820.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00820.xml.html new file mode 100644 index 000000000..46f35c460 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00820.xml.html @@ -0,0 +1,195 @@ + + + + + Use Case 00820:Adding a Bookmark + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00820:Adding a Bookmark

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ This Use Case addresses the need to add a bookmark to the bookmarks portlet. +

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: A Portal Participant encounters a knowledge item within an application that they would like to be able to return to easily
Preconditions: + +

+ This Use Case requires that the Participant have write privelage on the Bookmark Portlet application. +

+ + + +
Basic Path: + +


+

    +
  1. During the course of browsing content within a portal, a participant wishes to bookmark an item for quick retrieval + later.
  2. +
  3. The Participant clicks the "Add Bookmark" icon at the top of the portal to store the location of the content item in + the bookmark portlet. +
+

+ + + +
Postconditions: + +

+

+ + + +
Succesful End Conditions: + +

+ A link to the knowledge item appears in the Bookmarks portlet. +

+ + + +
Alternate Paths: + +

+ +

+ + + +
Exception Paths: + +

+ +

+ + + +
Failure End Conditions: + +

+ +

+ + + +
Sample Narrative: + +

+

+ + + +
Open Issues: + +


+

    +
  • Why are CW bookmarks better than browser bookmarks? Because they can be shared?
  • +
  • What action does a user take to save a bookmark? A "Save Bookmark" button? Should this be a persistent feature of the + portal UI?
  • +
  • What if the item that a user wishes to bookmark is within a portal + application, and the nav bar, help, and other ancillary links (where a + 'save bookmark' button would probably be located) are not present? Does + this imply that every (reasonable) application that populates the portal, needs to incorporate a "Bookmark This View" button + in it UI?
  • +
+

+ + + + + + +
Iteration: + Facade. + +
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2001/11/21 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00830.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00830.xml.html new file mode 100644 index 000000000..bbc4830bf --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00830.xml.html @@ -0,0 +1,198 @@ + + + + + Use Case 00830:Editing Bookmark Properties + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00830:Editing Bookmark Properties

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ This Use Case describes the action of modifying the properties of an existing bookmark. +

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: WP decides to modify bookmark
Preconditions: + +

+ This Use Case requires these three pre-conditions: +

    +
  1. The bookmark portlet is present in the portal.
  2. +
  3. At least one bookmark has been saved in the portlet.
  4. +
  5. The participant has write privilege on the bookmark application instance for this portal.
  6. +
+ +

+ + + +
Basic Path: + +


+

  1. Through the bookmark portlet, the participant launches the bookmark application.
  2. +
  3. The bookmark application lists all bookmarks for that portal (and within the personal portal, all bookmarks available + in collaborative portals that the user participates in, if desired...)
  4. +
  5. The user then selects a bookmark
  6. +
  7. After a bookmark has been selected, A form is displayed with all pertinent information about the bookmark, such as:
  8. +
    • Creation date
    • +
    • The name of the person who created it.
    • +
    • The name of the bookmark (A modifiable field)
    • +
    • The target URL (A modifiable field)
    • +
    • The name of the portal it is associated with
    • +
    • A link that says Delete This Bookmark
    +
  9. The user can change the name or the target of the bookmark, by modifying + the values in the modifiable field, then press the save button
  10. + +
+

+ + + +
Postconditions: + +

+

+ + + +
Succesful End Conditions: + +

+ The desired property is modified. +

+ + + +
Alternate Paths: + +

+ If properties are opened up for a bookmark that the participant does NOT have write privileges, then the properties are displayed + as unmodifiable fields (i.e., labels instead of text fields). + +

+ + + +
Exception Paths: + +

+ +

+ + + +
Failure End Conditions: + +

+ +

+ + + +
Sample Narrative: + +

+

+ +

Open Issues:
+

+ + + + + + +
Open Issues:
Iteration: + Focused + +
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2001/11/21 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00840.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00840.xml.html new file mode 100644 index 000000000..2afbcd4fb --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00840.xml.html @@ -0,0 +1,183 @@ + + + + + Use Case 00840:Deleting a Bookmark + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00840:Deleting a Bookmark

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + +

+ This Use Case addresses the need to occasionally remove a bookmark from the bookmark portlet. +

+ + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: A Portal Participant would like to remove a bookmark link from the bookmark portlet
Preconditions: + +

+ This Use case requires the Participant to have write/delete privelage on + the Bookmarks application/Portlet for this portal. +

+ + + +
Basic Path: + +


+

    +
  1. The participant clicks the "edit bookmarks" icon on the bookmarks portlet/
  2. +
  3. The Participant clicks the "delete bookmark" link next to the bookmark to be deleted. +
+

+ + + +
Postconditions: + +

+

+ + + +
Succesful End Conditions: + +

+ The link to the knowledge item is removed from the Bookmarks portlet. +

+ + + +
Alternate Paths: + +

+ +

+ + + +
Exception Paths: + +

+ +

+ + + +
Failure End Conditions: + +

+ +

+ + + +
Sample Narrative: + +

+

+ + + +
Open Issues: + +


+

+ + + + + +
Iteration: + Focused + +
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2001/11/21 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00900.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00900.xml.html new file mode 100644 index 000000000..2a63a5bd7 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00900.xml.html @@ -0,0 +1,125 @@ + + + + + Use Case 00900:Select a Theme for a Portal + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00900:Select a Theme for a Portal

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description: + + The theme for a portal determines its look & feel. This use case is employed when an administrator is unhappy with the look + and feel of a portal. + + +
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: The administrator is unhappy with the current look and feel.
Preconditions: + + This use case depends on at least two themes being installed on the portalserver. The current plan is to have five + pre-installed themes on every portalserver deployment. + + +
Basic Path: + +
    +
  1. The PA selects the 'Configure Portal' link.
  2. +
  3. The PA then selects the 'Themes' tab on the portal configuration page.
  4. +
  5. A list of available themes is displayed with check boxes next to them. The portals current theme has the checkbox next + to it pre-selected. In addition, a thumbnail of the look and feel for the currently selected theme is displayed
  6. +
  7. The PA selects the desired theme, and the thumbnail changes to reflect this selection. This step may iterate...
  8. +
  9. After finalizing on a theme, the PA clicks the 'Save Theme' button
  10. +
  11. The PA is returned to the Configure Portal layout tab.
  12. +
+ + +
Postconditions:
Succesful End Conditions: + The desired theme is now used to render the portal. + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration: Filled
Status: ready_for_review
+

+ by Jim Parsons +

+ Last Modified: 2003/02/26 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00910.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00910.xml.html new file mode 100644 index 000000000..c615304c0 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00910.xml.html @@ -0,0 +1,113 @@ + + + + + Use Case 00910:Create a Theme for a Portal + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00910:Create a Theme for a Portal

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: user_goal
Actors: +
    +
  • Portal Administrator
  • +
+
Trigger: A desired Look and Feel is not available in the list of currently installed themes.
Preconditions:
Basic Path: + +
    +
  1. The PA clicks the 'Create Theme' button on the Themes tab in the Configure Portal area
  2. +
  3. The PA is taken to the theme creation page
  4. +
  5. The currently selected theme is pre-loaded into the UI, so that PA's can easily make incremental changes.
  6. +
  7. The PA creates the theme. Individual aspects of this process are detailed in use cases psrv-00950 through psrv-00970
  8. +
  9. When satisfied, the PA clicks the 'Save Theme' button.
  10. +
  11. The UI prompts the PA for a name for the theme. After entering one, the PA clicks 'Save' and the PA is returned to the + Configure Portal Themes tab, where the new theme appears in the list.
  12. +
+ + +
Postconditions:
Succesful End Conditions: + Description of success from the user's point of view. + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration:
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2003/02/26 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00951.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00951.xml.html new file mode 100644 index 000000000..18808cc56 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00951.xml.html @@ -0,0 +1,108 @@ + + + + + Use Case 00951:Set Context Bar Color for Theme + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00951:Set Context Bar Color for Theme

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: subfunction
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: User wishes to set a color for Context Bar
Preconditions:
Basic Path: + +
    +
  1. User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  2. +
  3. User locates section of Create Theme form for Context bar and either selects one of the preset colors, or enters a custom + value.
  4. +
+ + +
Postconditions:
Succesful End Conditions: + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration: Focused
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2003/02/26 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00952.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00952.xml.html new file mode 100644 index 000000000..437c95a46 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00952.xml.html @@ -0,0 +1,108 @@ + + + + + Use Case 00952:Set Active Tab Color for Theme + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00952:Set Active Tab Color for Theme

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: subfunction
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: User wishes to set a color for Active Tabs
Preconditions:
Basic Path: + +
    +
  1. User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  2. +
  3. User locates section of Create Theme form for Active Tab and either selects one of the preset colors, or enters a custom + value.
  4. +
+ + +
Postconditions:
Succesful End Conditions: + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration: Focused
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2003/02/26 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00953.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00953.xml.html new file mode 100644 index 000000000..1fb689430 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00953.xml.html @@ -0,0 +1,108 @@ + + + + + Use Case 00953:Set Inactive Tab Color for Theme + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00953:Set Inactive Tab Color for Theme

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: subfunction
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: User wishes to set a color for Inactive Tab
Preconditions:
Basic Path: + +
    +
  1. User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  2. +
  3. User locates section of Create Theme form for Inactive Tab and either selects one of the preset colors, or enters a custom + value.
  4. +
+ + +
Postconditions:
Succesful End Conditions: + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration: Focused
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2003/02/26 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00954.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00954.xml.html new file mode 100644 index 000000000..75651f932 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00954.xml.html @@ -0,0 +1,108 @@ + + + + + Use Case 00954:Set Active Tab Text Color for Theme + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00954:Set Active Tab Text Color for Theme

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: subfunction
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: User wishes to set a color for Active Tab Text Color
Preconditions:
Basic Path: + +
    +
  1. User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  2. +
  3. User locates section of Create Theme form for Active Tab Text Color and either selects one of the preset colors, or enters + a custom value.
  4. +
+ + +
Postconditions:
Succesful End Conditions: + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration: Focused
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2003/02/26 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00955.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00955.xml.html new file mode 100644 index 000000000..f525fd541 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00955.xml.html @@ -0,0 +1,108 @@ + + + + + Use Case 00955:Set Inactive Tab Text Color for Theme + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00955:Set Inactive Tab Text Color for Theme

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: subfunction
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: User wishes to set a color for Inactive Tab Text
Preconditions:
Basic Path: + +
    +
  1. User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  2. +
  3. User locates section of Create Theme form for Inactive Tab Text and either selects one of the preset colors, or enters + a custom value.
  4. +
+ + +
Postconditions:
Succesful End Conditions: + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration: Focused
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2003/02/26 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00956.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00956.xml.html new file mode 100644 index 000000000..033397747 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00956.xml.html @@ -0,0 +1,108 @@ + + + + + Use Case 00956:Set Top Rule Under Tabs Color for Theme + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00956:Set Top Rule Under Tabs Color for Theme

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: subfunction
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: User wishes to set a color for Top Rule
Preconditions:
Basic Path: + +
    +
  1. User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  2. +
  3. User locates section of Create Theme form for Top Rule Under Tabs and either selects one of the preset colors, or enters + a custom value.
  4. +
+ + +
Postconditions:
Succesful End Conditions: + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration: Focused
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2003/02/26 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00957.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00957.xml.html new file mode 100644 index 000000000..cc1a10e8e --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00957.xml.html @@ -0,0 +1,108 @@ + + + + + Use Case 00957:Set Top Rule No Tabs Color for Theme + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00957:Set Top Rule No Tabs Color for Theme

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: subfunction
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: User wishes to set a color for Top Rule with no Tabs
Preconditions:
Basic Path: + +
    +
  1. User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  2. +
  3. User locates section of Create Theme form for Top Rule No Tabs and either selects one of the preset colors, or enters + a custom value.
  4. +
+ + +
Postconditions:
Succesful End Conditions: + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration: Focused
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2003/02/26 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00958.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00958.xml.html new file mode 100644 index 000000000..6ab6e743a --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00958.xml.html @@ -0,0 +1,108 @@ + + + + + Use Case 00958:Set Bottom Rule Color for Theme + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00958:Set Bottom Rule Color for Theme

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: subfunction
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: User wishes to set a color for Bottom Rule
Preconditions:
Basic Path: + +
    +
  1. User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  2. +
  3. User locates section of Create Theme form for Bottom Rule and either selects one of the preset colors, or enters a custom + value.
  4. +
+ + +
Postconditions:
Succesful End Conditions: + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration: Focused
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2003/02/26 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00959.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00959.xml.html new file mode 100644 index 000000000..1f0fb63a7 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00959.xml.html @@ -0,0 +1,108 @@ + + + + + Use Case 00959:Set Portlet Header Color for Theme + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00959:Set Portlet Header Color for Theme

+

+

Release Target:

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: subfunction
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: User wishes to set a color for Context Bar
Preconditions:
Basic Path: + +
    +
  1. User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  2. +
  3. User locates section of Create Theme form for Context bar and either selects one of the preset colors, or enters a custom + value.
  4. +
+ + +
Postconditions:
Succesful End Conditions: + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration: Focused
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2003/02/26 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/html/psrv-00960.xml.html b/ccm-portalserver/doc/use-cases/html/psrv-00960.xml.html new file mode 100644 index 000000000..02cae3d1d --- /dev/null +++ b/ccm-portalserver/doc/use-cases/html/psrv-00960.xml.html @@ -0,0 +1,108 @@ + + + + + Use Case 00960:Set Portlet Icon Color for Theme + + + + + + + + + +
CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat
+

Use Case 00960:Set Portlet Icon Color for Theme

+

+

Release Target: 2.0

+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description:
Goal Level: subfunction
Actors: +
    +
  • Portal Participant
  • +
+
Trigger: User wishes to set a color for Portlet Icon area
Preconditions:
Basic Path: + +
    +
  1. User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  2. +
  3. User locates section of Create Theme form for PortletIcon and either selects one of the preset colors, or enters a custom + value.
  4. +
+ + +
Postconditions:
Succesful End Conditions: + +
Alternate Paths:
Exception Paths:
Failure End Conditions:
Sample Narrative:
Open Issues:
Iteration: Focused
Status: in_progress
+

+ by Jim Parsons +

+ Last Modified: 2003/02/26 + + \ No newline at end of file diff --git a/ccm-portalserver/doc/use-cases/htmlize.xsl b/ccm-portalserver/doc/use-cases/htmlize.xsl new file mode 100644 index 000000000..2001efd36 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/htmlize.xsl @@ -0,0 +1,182 @@ + + + + +2.0 + + + + + +Use Case <xsl:value-of select="id/@number"/>:<xsl:value-of select="title"/> + + + + + + + + + +
+ CCM Portalserver Project > + Use Cases Index Page > + + CCM Central | + Red Hat +
+ + + +

Use Case :

+

+

Release Target:

+
+ +

Use Case :

+

+

Release Target:

+
+
+

+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Description: + + +
+Goal Level: + + +
+Actors: + +
    + +
  • +
    +
+
+Trigger: + + +
+Preconditions: + + +
+Basic Path: + + +
+Postconditions: + + +
+Succesful End Conditions: + + +
+Alternate Paths: + + +
+Exception Paths: + + +
+Failure End Conditions: + + +
+Sample Narrative: + + +
+Open Issues: + + +
+Iteration: + + +
+Status: + + +
+

+by +

+Last Modified: + + + +
+ +
diff --git a/ccm-portalserver/doc/use-cases/index.xsl b/ccm-portalserver/doc/use-cases/index.xsl new file mode 100644 index 000000000..017b8e27b --- /dev/null +++ b/ccm-portalserver/doc/use-cases/index.xsl @@ -0,0 +1,15 @@ + + + + + + + + + &nbsp;&nbsp; + + + + + diff --git a/ccm-portalserver/doc/use-cases/psrv-00001.xml b/ccm-portalserver/doc/use-cases/psrv-00001.xml new file mode 100644 index 000000000..e091fde55 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00001.xml @@ -0,0 +1,125 @@ + + + + Create a new portal + + + + + + The Portal Administrator makes new Portals available by performing the following steps:

+ +
    +
  • Creating a new portal.
  • +
  • Creating the group of Portal Participants for that portal.
  • +
  • Creating portal tabs, if desired, for the portal.
  • +
  • Adding the appropriate portlets to the portal and portal tabs.
  • +
  • Configuring layout and look & feel for the portal.
  • +
+ +

The Portal Administrator has two possible procedures for creating portals:

+ +
    +
  • Creating a new portal from scratch.
  • +
  • Creating a new portal by using a portal template. (See Alternate Paths)
  • +
+ +

While creating a portal, the Portal Administrator assigns the following properties:

+ +
    +
  • Portal Name - the name by which the portal is identified in the Web site.
  • +
  • Portal Mission - a brief description of the purpose that the portal is intended to fulfill.
  • +
  • Portal URL Label - the label of the Web site stub at which the portal appears.
  • +
+ + + ]]> +
+ + + + + User has general +permission to create portals. +

+ + ]]> +
+ + + +
    + +
  1. The Portal Administrator navigates to the creation interface + via the portal administration home page.
  2. + +
  3. She specifies a name for the portal.
  4. + +
  5. She specifies a URL stub for the portal.
  6. + +
  7. She optionally writes up a "mission statement" for the portal.
  8. + +
+ +

+ + ]]> +
+ + A new portal is +created, with the user who created it identified as its +administrator.

+ + ]]> +
+ + A new +portal is created, with the creating user named as a participant in +the portal with administrative privileges, and the Administrator is +redirected to the new portal's configuration page.

+ + ]]> +
+ + PSRV_00002:Create a New Portal from a Pre-defined Template + + ]]> + + +

+
    +
  • EXC-1: The Administrator does not have + permission to create new portals.
  • +
  • EXC-2: The specified URL stub contains + characters that are illegal for URLs.
  • +
  • EXC-3: The specified URL stub is already in + use by another portal.
  • +
+

+ + ]]> +
+ + +

+ + ]]> +
+ +

+ + ]]> +
+ +Finished + +
diff --git a/ccm-portalserver/doc/use-cases/psrv-00002.xml b/ccm-portalserver/doc/use-cases/psrv-00002.xml new file mode 100644 index 000000000..ecfef45cf --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00002.xml @@ -0,0 +1,102 @@ + + + + + Create a New Portal from a Pre-defined Template + + + + + + A Portal +Administrator may create a new portal from an existing template. She controls the portal's location in the portal hierarchy, its name, its URL +stub, and its mission statement.

+ + ]]> +
+ + + + + + + + + +
    + +
  1. The Portal Administrator navigates to the portal creation + interface via the portal administration home page.
  2. + +
  3. She specifies a name for the new portal.
  4. + +
  5. She specifies a URL stub for the new portal.
  6. + +
  7. She optionally writes up a "mission statement" for the new portal.
  8. + +
  9. She clicks the "Create from existing template" button.
  10. + +
  11. She is presented with a list of templates and selects the one she wishes to use for the new portal. If desired, she can click the preview link of any template to visit a read-only version of that portal configuration.
  12. + +
  13. If there is a participant list associated with her template selection, she can check a checkbox which specifies whether or not all participants associated with the template should be included in the new portal.
  14. + +
  15. Finally, she finishes by clicking the "Create Portal" button. + +
+

+See PSRV-00002:Create a Portal Template for how to go about creating a template. + + ]]> +
+ +

+ + ]]> +
+ + A new +portal is created, with the creating user named as a participant in +the portal with administrative privileges, and with all application +and portlet configuration copied over from the selected portal template. +Participants may be copied as well.

+ + ]]> +
+ +

+ + ]]> +
+ +

+ + ]]> +
+ +

+ + ]]> +
+ +

+ + ]]> +
+ +

+ + ]]> +
+Facade +
diff --git a/ccm-portalserver/doc/use-cases/psrv-00003.xml b/ccm-portalserver/doc/use-cases/psrv-00003.xml new file mode 100644 index 000000000..d93881d43 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00003.xml @@ -0,0 +1,76 @@ + + + + + Create a Portal Template + + + + + + A Portal +Administrator may create and configure portal templates. +

+ + ]]> +
+ + + + + User has general +permission to create portal templates.

+ + ]]> +
+ + + +To be determined... +

+ + ]]> +
+ + A new portal template is created. +

+ + ]]> +
+ + + + +

+ + ]]>
+ + + + +

+ + ]]> +
+ +

+ +

Open Issues:

+ + ]]> +
+ +Facade + +
diff --git a/ccm-portalserver/doc/use-cases/psrv-00010.xml b/ccm-portalserver/doc/use-cases/psrv-00010.xml new file mode 100644 index 000000000..c707a508b --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00010.xml @@ -0,0 +1,107 @@ + + + + + Modify basic portal configuration + + + + + + A Portal +Administrator may modify the basic configuration of its portal, +including its name, mission statement, layout, and look & feel.

+ + ]]> +
+ + + + +

+ + ]]> +
+ + + +
    + +
  1. The Portal Administrator navigates to the configuration + page for the portal by selecting the link 'Configure Portal'.
  2. + +
  3. She chooses the 'Basic' tab to modify: +
  4. + +
  5. She chooses the 'Layout' tab to: +
  6. + +
+ +

+ + ]]> +
+ +

+ + ]]> +
+ + The basic +attributes of the portal are updated.

+ + ]]> +
+ +

+ + ]]> +
+ +

+ + ]]> +
+ +

+ + ]]> +
+ +

+ + ]]> +
+ +

+ +
+ + + ]]> +
+ +Filled + +
diff --git a/ccm-portalserver/doc/use-cases/psrv-00011.xml b/ccm-portalserver/doc/use-cases/psrv-00011.xml new file mode 100644 index 000000000..fe36d74b0 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00011.xml @@ -0,0 +1,28 @@ + + + + + Modify Portal Mission + + + + + + + + + +
  • Starting at the Portal, A PA navigates to the Portal Configuration page by clicking the "Configure Portal" link
  • +
  • On the Portal Configuration page, the PA selects the 'basic' tab.
  • +
  • The PA then edits the mission statement for the Portal, and clicks save.
  • + +

    + ]]> +
    + + + +Filled + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00012.xml b/ccm-portalserver/doc/use-cases/psrv-00012.xml new file mode 100644 index 000000000..b4bb79d1c --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00012.xml @@ -0,0 +1,86 @@ + + + + + Modify Portal Name + + + + + +A method for changing the name of an existing Portal. +

    + + ]]> +
    + + + + +

    + + ]]> +
    + +
    +
      +
    1. Starting at the Portal, A PA navigates to the Portal Configuration page by clicking the "Configure Portal" link
    2. +
    3. On the Portal Configuration page, the PA selects the 'basic' tab.
    4. +
    5. The PA then enters the new name for the Portal, and clicks save.
    6. +
    +

    + + ]]> +
    + +

    + + ]]> +
    + + +The name of the Portal is changed to the desired name. +

    + + ]]> +
    + +

    + + ]]> +
    + +

    + + ]]> +
    + +

    + + ]]> +
    + +

    + + ]]> +
    + + + + +Focused + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00014.xml b/ccm-portalserver/doc/use-cases/psrv-00014.xml new file mode 100644 index 000000000..b5a9a52c9 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00014.xml @@ -0,0 +1,106 @@ + + + + + Modify Portal URL Stub + + + + + + +A method is needed for a Portal Administrator to change the final portion of a portal URL that refers to the Portal location on the Site Map. +

    + + ]]> +
    + + + + + + +

    + + ]]> +
    + +
    +
      +
    1. Within the Portal, the PA clicks on the link for Portal Configuration
    2. +
    3. The PA locates a Text Field on the page named URL Stub. The current stub name is pre-loaded within this field
    4. +
    5. The PA changes the value within this field to the name he or she prefers
    6. +
    7. The PA clicks on the "Save Configuration" button
    8. +
    9. The PA is returned to the Portal Configuration page
    10. +
    +

    + + ]]> +
    + + +

    + + ]]> +
    + + +The URL Stub name is successfully changed +

    + + ]]> +
    + + + +

    + + ]]> +
    + + +Two possible exceptions to this Use Case are: +
      +
    • The URL Stub text field is left blank. In this case, the config page is redisplayed with the error explained in red text next to the text field, such as "Required Field"
    • +
    • The URL Stub name entered has whitespace or unacceptable characters in it.If so, the config page is redisplayed with a message in red text explaining the nature of the error, such as "unacceptable character '!'
    • +
    +

    + + ]]> +
    + + + +

    + + ]]> +
    + + +

    + + ]]> +
    + +
    +

    + + +

    + + ]]> +
    + +Facade + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00015.xml b/ccm-portalserver/doc/use-cases/psrv-00015.xml new file mode 100644 index 000000000..5c1c2c04e --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00015.xml @@ -0,0 +1,101 @@ + + + + + Move Portal + + + + + + A Global Portal +Administrator may move around portals within the portal +hierarchy.

    + + ]]> +
    + + + + +

    + + ]]> +
    + + + +
      + +
    1. The Portal Administrator navigates to "Move Portal" + interface under global portal management.
    2. + +
    3. She selects the portal to be moved. (The toplevel portal may not be selected.)
    4. + +
    5. She selects the new parent for the portal being moved.
    6. + +
    7. She reviews the planned change.
    8. + +
    9. She confirms the change.
    10. + +
    + +

    + + ]]> +
    + +

    + + ]]> +
    + + The first +portal specified is moved in the hierarchy so that it's parent is +the second portal specified. The children of the moved portal +move with it.

    + + ]]> +
    + +

    + + ]]> +
    + +

    + + ]]> +
    + +

    + + ]]> +
    + +

    + + ]]> +
    + +

    + +
    + + + ]]> +
    + +Facade + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00030.xml b/ccm-portalserver/doc/use-cases/psrv-00030.xml new file mode 100644 index 000000000..199b9e86a --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00030.xml @@ -0,0 +1,97 @@ + + + + + Navigate to a related portal + + + + + + A Portal Participant +sees and can navigate to portals related to the one currently under +scrutiny. A related portal may be merely associated or it may +additionally be a "child" portal to the current portal.

    + + ]]> +
    + + + + + +
      +
    1. The current portal must have at least one portal in relation to it, +and that portal must be accessible by the user.
    2. +
    3. The current portal must have a Navigator Portlet installed.
    4. +
    +

    + + ]]> +
    + + + +
      +
    1. The user visits the portal home page.
    2. + +
    3. The system displays a list of related portals that the user + has access to. If a related portal is a child of the current + portal, it is marked as such.
    4. + +
    5. The user selects one of the portals and navigates to it.
    6. + +
    7. The chosen portal appears in place of the old one. +
    + +

    + + ]]> +
    + +

    + + ]]> +
    + + The user +reaches a related portal.

    + + ]]> +
    + +

    + + ]]> +
    + +

    + + ]]> +
    + +

    + + ]]> +
    + +

    + + ]]> +
    + +

    + + ]]> +
    +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00033.xml b/ccm-portalserver/doc/use-cases/psrv-00033.xml new file mode 100644 index 000000000..522489fe2 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00033.xml @@ -0,0 +1,56 @@ + + + + + Add another Portal as a Related Portal + + + + + + +A Portal Administrator (PA) wishes to add a reference to his or her Portal to a Related Portal. +

    + + ]]> +
    + + + + + +It is a necessary pre-condition for this Use Case, that at least one other Portal has granted "Related Portal" access. +

    + + ]]> +
    + +
    +
      +
    1. The PA clicks on the Configure Portal link
    2. +
    3. The PA then the Related Portals Tab
    4. +
    5. The PA is presented with a list of Portals on the system that have granted access as a related portal to the PA's portal group. Note: Those Portals that are already listed as related Portals are listed, but grayed out.
    6. +
    7. The PA selects a Portal from the list
    8. +
    9. The PA then clicks the Add Related Portal button on this configuration page
    10. +
    11. The PA is returned to the Portal Tab Configuration page. +
    +

    + + ]]> +
    + + +The new related Portal appears within the Related Portals portlet. +

    + + + ]]> +
    + +Focused + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00050.xml b/ccm-portalserver/doc/use-cases/psrv-00050.xml new file mode 100644 index 000000000..04db4c64a --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00050.xml @@ -0,0 +1,106 @@ + + + + + Browse portal participants + + + + + + A Portal Participant +wishes to browse through a listing of all participants in the +portal.

    + + ]]> +
    + + + + + + + +
    +
      +
    1. The Portal Participant navigates to the "Participants" + listing screen for the portal.
    2. +
    3. The participant is presented with a listing of all participants + in the portal and certain frequently-needed information. If + the number of participants exceeds some threshold, the list will + be broken up into multiple pages, with links for quick access to + partcipants whose names begin with particular letters of the + alphabet.
    4. +
    5. Each entry in the provided list will include a link to drill + down to the "One Participant" view. See PSRV-00052 ("View a single participant's + activities and roles within a portal") for a description of + this view.
    6. +
    +

    + + ]]> +
    + + +

    + + ]]> +
    + + The user is +able to view listings of participants within the portal, and drill +down to detailed views of individual participants.

    + + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + +

    + + ]]> +
    + +
    +

    + + + ]]> +
    + +Focused + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00051.xml b/ccm-portalserver/doc/use-cases/psrv-00051.xml new file mode 100644 index 000000000..66f472b3c --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00051.xml @@ -0,0 +1,98 @@ + + + + + Search for a portal participant + + + + + A Portal Participant +wants to find participants in a portal meeting certain +criteria.

    + + ]]> +
    + + + + + +

    + + ]]> +
    + +
    +
      +
    1. The Participant navigates to the "People" tab in the + Configure Portal area, and clicks on the "search" link.
    2. +
    3. The Participant specifies search criteria, which may include + participant name and role assignments.
    4. +
    5. The Participant is presented with a set of matching + participants. This listing format shall be the same as that + described in as the browse listing described in PSRV-00050 ("Browse Portal + Participants").
    6. +
    +

    + + ]]> +
    + + +

    + + ]]> +
    + + +The Participant finds participants matching the specified criteria. +

    + + + ]]> +
    + + +

    + + ]]> +
    + + +

    + + ]]> +
    + + +

    + + ]]> +
    + + +

    + + ]]> +
    + + + + +Focused + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00052.xml b/ccm-portalserver/doc/use-cases/psrv-00052.xml new file mode 100644 index 000000000..e772399d6 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00052.xml @@ -0,0 +1,115 @@ + + + + + View/Administer a single participant + + + + + + A Portal Participant +wishes to view various information about a specific portal +participant. A Portal Administrator may also want to perform +various other administrative tasks on a participant.

    + + ]]> +
    + + + + + + +

    + + ]]> +
    + +
    +
      + +
    1. The Portal Participant locates the participant they are + interested in via PSRV-00051:Search for a portal participant.
    2. +
    3. The Participant clicks on a "view" link next to the name of the + participant of interest.
    4. +
    5. The resulting view page presents the Participant with a history + of the selected participant as well as their other activities, + and also various other information specific to the selected participant, + such as their role assignments in the portal. In addition, this view + will present data on the user that is not associated with any + portal, such as position in the organization structure and + contact information.
    6. +
    +

    + + ]]> +
    + + +

    + + ]]> +
    + + The user is +able to view listings of participants within the portal, and drill +down to detailed views of individual participants.

    + + + ]]> +
    + + +
      +
    • When viewed by an Administrator, this page will also serve as + a participant administration page: UI will be provided for + adjusting their role assignments (See PSRV-00065), for + removing the participant from the portal (See PSRV-00056), and for any other + administrative tasks that are identified.

      +
    • +
    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + + + ]]> +
    + + +

    + + ]]> +
    + +None + + + +Focused + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00055.xml b/ccm-portalserver/doc/use-cases/psrv-00055.xml new file mode 100644 index 000000000..c10db736d --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00055.xml @@ -0,0 +1,115 @@ + + + + + Add a portal participant + + + + + A Portal Administrator +wants to add a participant to a portal.

    + + ]]> +
    + + + + + +

    + + ]]> +
    + +
    +
      + +
    1. The Portal Administrator navigates to the "Participants" + screen for the portal to which participants are to be + added.
    2. +
    3. The Administrator then clicks on the "Add New Participant" link.
    4. +
    5. The Administrator then types in a name or email address to search for + the users and groups that might be added.
    6. +
    7. A list of matches is returned. The Administrator clicks on the + name of the party to be made a participant.
    8. +
    9. The Administrator selects the role(s) the participant is to play + in the portal.
    10. +
    +

    + + ]]> +
    + + +

    + + ]]> +
    + + +The selected parties are made participants in the portal, with the +specified roles. +

    + + + ]]> +
    + + +

    + + ]]> +
    + + +

    + + ]]> +
    + + +

    + + ]]> +
    + + +

    + + ]]> +
    + +
    +
      +
    • Should people who are already participants show up in the search + results? Leaving them out could prove annoying in situations + where the Administrator does not know that the party they're + looking for is already a participant. Including existing + participants, with some sort of flag indicating that they're + already participants (and linking to the "View/Administer a single + participant" page (PSRV-00052) may + make more sense.
    • +
    +

    + + + + + + ]]> +
    + +Focused + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00056.xml b/ccm-portalserver/doc/use-cases/psrv-00056.xml new file mode 100644 index 000000000..8ea34313f --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00056.xml @@ -0,0 +1,107 @@ + + + + + Remove a portal participant + + + + + + A Portal Administrator +wants to remove a participant from a portal.

    + + ]]> +
    + + + + + + +

    + + ]]> +
    + +
    +
      +
    1. The Portal Administrator navigates to the "View One + Participant" page, using PSRV-00052.
    2. +
    3. The Administrator clicks on a "Remove this participant" link.
    4. +
    5. The Administrator is returned to the portal's "Participants" + page.
    6. +
    +

    + + ]]> +
    + + +

    + + ]]> +
    + + +The selected party is removed as a participant of the portal. +

    + + + ]]> +
    + + + +

    + + ]]> +
    + + +
      +
    • If removing a participant will leave some responsibility/role + unassigned, the administrator should be presented with a + confirmation screen that lists these responsibilities and asks the + administrator to confirm the removal decision. This screen may + also provide shortcuts for re-assigning those responsibilities to + new roles or individuals.
    • +
    +

    + + ]]> +
    + + + +

    + + ]]> +
    + + +

    + + ]]> +
    + + + + +Filled. + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00057.xml b/ccm-portalserver/doc/use-cases/psrv-00057.xml new file mode 100644 index 000000000..a7c1aea61 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00057.xml @@ -0,0 +1,19 @@ + + + + + Invite a participant to a portal + + + + + + + + + Basic path for the use case + + + Description of success from the user's point of view. + + diff --git a/ccm-portalserver/doc/use-cases/psrv-00065.xml b/ccm-portalserver/doc/use-cases/psrv-00065.xml new file mode 100644 index 000000000..19ebe49f8 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00065.xml @@ -0,0 +1,102 @@ + + + + + Modify a participant's role assignments + + + + + + A Portal Administrator +wants to modify a participant's role assignments.

    + + ]]> +
    + + + + + +

    + + ]]> +
    + +
    +
      +
    1. The Portal Administrator navigates to the "View One + Participant" page, using PSRV-00052.
    2. +
    3. The Administrator is provided with a set of checkboxes for + the roles available in the current portal. Boxes for the roles + that the participant already possesses are already checked.
    4. +
    5. The Administrator checks and unchecks boxes to change role + assignments.
    6. +
    7. The Administrator clicks an "Update Role Assignments" button to + confirm the changes.
    8. +
    +

    + + ]]> +
    + + +

    + + ]]> +
    + + +The desired role assignment changes are made. +

    + + + ]]> +
    + + +

    + + ]]> +
    + + +

    + + ]]> +
    + + +

    + + ]]> +
    + + +

    + + ]]> +
    + +
    +

    + + + + ]]> +
    + +Focused + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00100.xml b/ccm-portalserver/doc/use-cases/psrv-00100.xml new file mode 100644 index 000000000..b1dbfdb59 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00100.xml @@ -0,0 +1,74 @@ + + + + + Add a Tab to a Portal + + + + + + +The Portal administrator should be able to create and save tabs within a portal. +

    + + ]]> +
    + + + + + +Of course, this Use Case relies on the existence of a Portal in the first place. Every new portal is built with a default tab. +This tab is named "Main". The name of this tab, or any other tab can be +changed within the tab configuration page (See PSRV-00110:Configure a Portal Tab Use Case). +

    + + + ]]> +
    + +
    +
      +
    1. The PA visits the Portal Home page.
    2. +
    3. The PA selects the Configure Portal link
    4. +
    5. The PA then selects the link for 'Create a New Portal Tab'
    6. +
    7. The PA then enters a name for the new Portal Tab(this is a required field)
    8. +
    9. The PA then clicks the Create Tab button
    10. +
    11. The PA is then taken to the Configuration page for the new Tab
    12. +
    +

    + + ]]> +
    + + +The new tab is created, and available for customization. +

    + + ]]> +
    + + + + + +

    + + ]]> +
    + + + + +Finished + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00110.xml b/ccm-portalserver/doc/use-cases/psrv-00110.xml new file mode 100644 index 000000000..91931c452 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00110.xml @@ -0,0 +1,107 @@ + + + + + Configure A Portal Tab + + + + + + +Tabs are the principle organizational mechanism for restricting view clutter and focusing Portal data and function. This Use Case describes the procedure to follow when a modification to a Tab is desired. +

    + + ]]> +
    + + + + + + +

    + + ]]> +
    + +
    +
      +
    1. Starting at the Portal, he PA selects the "Configure Portal" link.
    2. +
    3. The 'Layout' tab is chosen next.
    4. +
    5. At the Configure Portal page, the PA is presented a list of all Tabs currently residing within the Portal. The PA selects a Tab to configure.
    6. +
    7. The PA makes the desired configuration changes and then clicks the "Save Configuration" button. Configuration changes available include: +
    8. +
    +

    + + ]]> +
    + + +

    + + ]]> +
    + + +The desired config changes are made and saved. +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + +

    + + ]]> +
    + +
    +

    + + + ]]> +
    + +Focused + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00120.xml b/ccm-portalserver/doc/use-cases/psrv-00120.xml new file mode 100644 index 000000000..b3e3fcd7c --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00120.xml @@ -0,0 +1,58 @@ + + + + + Delete a Portal Tab + + + + + + +A Portal Administrator (PA) should have a method available for deleting an existing Portal Tab. +

    + + ]]> +
    + + + + + +It is necessary that the Portal contain more than the "Main" tab at the start of this Use Case. If a Portal only contains a "Main" tab, the Portal Configuration page will not offer the option to remove the "Main" Tab. +

    + + + + + ]]> +
    + +
    +
      +
    1. A PA selects the 'Configure Portal' link.
    2. +
    3. The PA scans the list of Portal Tabs associated with that Portal
    4. +
    5. The PA locates the tab he or she wishes to remove, and selects the 'Delete' link next to it.
    6. +
    7. A confirmation dialogue appears asking the PA to choose from two choices: +
      • "Proceed with Tab Deletion"
      • Or
      • Cancle
      +
    8. The PA is returned to the "Configure Portal" page. If "Proceed with Tab Deletion" was selected above, then the deleted tab no longer appears in the list of tabs associated with the Portal
    9. +
    +

    + + ]]> +
    + + +The tab that the PA desires to delete is removed. +

    + + ]]> +
    + +Filled + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00140.xml b/ccm-portalserver/doc/use-cases/psrv-00140.xml new file mode 100644 index 000000000..56aaca818 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00140.xml @@ -0,0 +1,50 @@ + + + + + Change Name of Existing Portal Tab + + + + + + +This Use Case describes the procedure for changing the name of an existing Portal tab. +

    + + ]]> +
    + + + + +
    +
      +
    1. The PA navigates to the Portal and selects the "Configure Portal" link.
    2. +
    3. The PA is presented with a list of all tabs associated with this Portal
    4. +
    5. The PA selects the tab that he wishes to rename.
    6. +
    7. The PA selects the "Rename Tab" link.
    8. +
    9. A small form is presented to the PA with a field for the tabs name.
    10. +
    11. The PA changes the name within the Text Field
    12. +
    13. The PA then clicks the "Save Configuration" button.
    14. +
    +

    + + ]]> +
    + + +The name of the Portal Tab is changed successfully. +

    + + + + ]]> +
    + +Focused + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00150.xml b/ccm-portalserver/doc/use-cases/psrv-00150.xml new file mode 100644 index 000000000..994aafb18 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00150.xml @@ -0,0 +1,28 @@ + + + + + Reorder Portal Tabs + + + + + + + + + +
  • The Portal Administrator selects the 'Configure Portal' link.
  • +
  • The PA then selects the portal tab from the list that he wishes to reposition.
  • +
  • When selected, repositioning arrows/links appear next to the tab.
  • +
  • The PA shifts the Tab right or left, as desired.
  • + + ]]> +
    + + + +Finished + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00200.xml b/ccm-portalserver/doc/use-cases/psrv-00200.xml new file mode 100644 index 000000000..939405b75 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00200.xml @@ -0,0 +1,101 @@ + + + + + Add a Portlet to a Portal Tab + + + + + + +This use case describes the series of events necessary to adding a portlet to an already existing Portal Tab +

    + + ]]> +
    + + + + + + +

    + + ]]> +
    + +
    +
      +
    1. Beginning at the Portal, a PA clicks the "Configure Portal" + link
    2. +
    3. On the Configure Portal page, the PA is presented with a list of all Tabs that currently reside within the Portal.
    4. +
    5. The PA chooses the Tab he or she would like to supplement with a new Portlet.
    6. +
    7. The PA then clicks the "Add/Remove" portlets. This launches a drop down box listing all portlets available on the system.
    8. +
    9. The PA check the Portlet he wishes to add.
    10. +
    +

    + + ]]> +
    + + +

    + + ]]> +
    + + +The desired Portlets are added to the Portal +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + +

    + + ]]> +
    + +
    +

    + + + ]]> +
    + +Focused + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00210.xml b/ccm-portalserver/doc/use-cases/psrv-00210.xml new file mode 100644 index 000000000..0c0694174 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00210.xml @@ -0,0 +1,101 @@ + + + + + Delete a Portlet from a Portal Tab + + + + + +This use case describes the series of events necessary to delete a portlet in an already existing Portal Tab +

    + + ]]> +
    + + + + + + +

    + + ]]> +
    + +
    +
      +
    1. Beginning at the Portal, a PA clicks the "Configure Portal" + link
    2. +
    3. On the Configure Portal page, the PA is presented with a list of all Tabs that currently reside within the Portal. Next to the name of each Tab, is a link saying "configure" and a link saying "delete".
    4. +
    5. The PA chooses the Tab he or she would like to delete a Portlet from, and chooses the "Configure" link for that Tab
    6. +
    7. The Tab configuration page presents the PA with an Option to "Add/Remove Portlets". The PA selects this link
    8. +
    9. On the Add/Remove Portlets page, all available Portlets appear as a checkable list, partitioned conveniently by Package Type. Portlets already included within this Tab are pre-checked, while unused available Portlets appear as unchecked
    10. +
    11. The PA unchecks those Portlets he or she wishes to remove, and then clicks the "Save Configuration"button
    12. +
    13. The PA is returned to the Tab configuration Page
    14. +
    +

    + + ]]> +
    + + +

    + + ]]> +
    + + +The desired Portlets are removed from the Portal +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + +

    + + ]]> +
    + +
    +

    + + ]]> +
    + +Focused + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00220.xml b/ccm-portalserver/doc/use-cases/psrv-00220.xml new file mode 100644 index 000000000..6ca6a17e5 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00220.xml @@ -0,0 +1,18 @@ + + + + + Change the Layout for a Portal Tab + + + + + + + + Basic path for the use case + + + Description of success from the user's point of view. + + diff --git a/ccm-portalserver/doc/use-cases/psrv-00230.xml b/ccm-portalserver/doc/use-cases/psrv-00230.xml new file mode 100644 index 000000000..d85108a8e --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00230.xml @@ -0,0 +1,18 @@ + + + + + Move a Portlet to a New Position Within a Portal Tab + + + + + + + + Basic path for the use case + + + Description of success from the user's point of view. + + diff --git a/ccm-portalserver/doc/use-cases/psrv-00240.xml b/ccm-portalserver/doc/use-cases/psrv-00240.xml new file mode 100644 index 000000000..7a7d0d757 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00240.xml @@ -0,0 +1,97 @@ + + + + + Configure a Portlet + + + + + +A Portal Administrator wishes to customize a portlet that currently resides +within a Tab in the Portal. +

    + + ]]> +
    + + + + + + +

    + + ]]> +
    + +
    +
      +
    1. Starting at the Portal, a PA clicks the Configure Portal link
    2. +
    + +

    + + ]]> +
    + + +

    + + ]]> +
    + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + +

    + + ]]> +
    + +
    +

    + + + + ]]> +
    + +Filled + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00310.xml b/ccm-portalserver/doc/use-cases/psrv-00310.xml new file mode 100644 index 000000000..548407e51 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00310.xml @@ -0,0 +1,18 @@ + + + + + Add an Application to a Portal + + + + + + + + Basic path for the use case + + + Description of success from the user's point of view. + + diff --git a/ccm-portalserver/doc/use-cases/psrv-00320.xml b/ccm-portalserver/doc/use-cases/psrv-00320.xml new file mode 100644 index 000000000..692ca0fef --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00320.xml @@ -0,0 +1,18 @@ + + + + + Remove an Application from a Portal + + + + + + + + Basic path for the use case + + + Description of success from the user's point of view. + + diff --git a/ccm-portalserver/doc/use-cases/psrv-00330.xml b/ccm-portalserver/doc/use-cases/psrv-00330.xml new file mode 100644 index 000000000..1b2eeaf1d --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00330.xml @@ -0,0 +1,18 @@ + + + + + Navigate to Applications Within a Portal + + + + + + + + Basic path for the use case + + + Description of success from the user's point of view. + + diff --git a/ccm-portalserver/doc/use-cases/psrv-00340.xml b/ccm-portalserver/doc/use-cases/psrv-00340.xml new file mode 100644 index 000000000..c15bd50ee --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00340.xml @@ -0,0 +1,18 @@ + + + + + Configure an Application Instance + + + + + + + + Basic path for the use case + + + Description of success from the user's point of view. + + diff --git a/ccm-portalserver/doc/use-cases/psrv-00400.xml b/ccm-portalserver/doc/use-cases/psrv-00400.xml new file mode 100644 index 000000000..86f545c53 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00400.xml @@ -0,0 +1,18 @@ + + + + + Create a Related Portal reference between two portals + + + + + + + + Basic path for the use case + + + Description of success from the user's point of view. + + diff --git a/ccm-portalserver/doc/use-cases/psrv-00405.xml b/ccm-portalserver/doc/use-cases/psrv-00405.xml new file mode 100644 index 000000000..adf61149a --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00405.xml @@ -0,0 +1,18 @@ + + + + + Remove a Related Portal reference between two portals + + + + + + + + Basic path for the use case + + + Description of success from the user's point of view. + + diff --git a/ccm-portalserver/doc/use-cases/psrv-00410.xml b/ccm-portalserver/doc/use-cases/psrv-00410.xml new file mode 100644 index 000000000..58094adc8 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00410.xml @@ -0,0 +1,93 @@ + + + + + Navigate to a related portal + + + + + A Portal Participant +sees and can navigate to portals related to the one currently under +scrutiny. A related portal may be merely associated or it may +additionally be a "child" portal to the current portal.

    + + ]]> +
    + + + + + The current portal +must have at least one portal in relation to it, and that portal +must be accessible by the user.

    + + ]]> +
    + + + +
      +
    1. The user visits the portal home page.
    2. + +
    3. The system displays a list of related portals that the user + has access to. If a related portal is a child of the current + portal, it is marked as such.
    4. + +
    5. The user selects one of the portals and navigates to it.
    6. + +
    7. The chosen portal appears in place of the old one, and the + system provides a way to navigate back.
    8. +
    + +

    + + ]]> +
    + +

    + + ]]> +
    + + The user +reaches a related portal.

    + + ]]> +
    + +

    + + ]]> +
    + +

    + + ]]> +
    + +

    + + ]]> +
    + +

    + + ]]> +
    + +

    + + ]]> +
    +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00500.xml b/ccm-portalserver/doc/use-cases/psrv-00500.xml new file mode 100644 index 000000000..ad5b37bce --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00500.xml @@ -0,0 +1,110 @@ + + + + + Archive a Portal + + + + + +A Portal set up for a particular project team is archived when the project is completed. +

    + + ]]> +
    + + + + + + +

    + + ]]> +
    + +
    + +
      +
    1. The administrator visits the Portal homepage.
    2. +
    3. The administrator clicks on the "Configure Portal" link.
    4. +
    5. The administrator chooses the "Archive Portal" link.
    6. +
    7. The administrator is prompted to enter any comments he or she wishes to associate with the archived Portal.
    8. +
    9. A confirmation message and button is displayed asking if the administrator is sure that he or she wishes to unlink the Portal from the active sitemap to be stored.
    10. +
    11. A "Successfully Archived" page is displayed.
    12. +
    +

    + + ]]> +
    + + +In archived state, a Portal is available to the non-administrative users as a Read-Only Portal. Administrators can still access the configuration page for the archived Portal, and modify the user access list for the Portal. +
    +
    + In addition, an administrator can "un-archive" a Portal if desired, but this is a separate use case! + +

    + + ]]> +
    + + +The Portal is successfully archived below the "/archived-portals" node, and is accessible by Portal group members in Read Only mode. + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + + +

    + + ]]> +
    + +
    +

    + + + + ]]> +
    + +Filled. + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00501.xml b/ccm-portalserver/doc/use-cases/psrv-00501.xml new file mode 100644 index 000000000..5ae97710a --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00501.xml @@ -0,0 +1,18 @@ + + + + + Un-Archive a Portal + + + + + + + + Basic path for the use case + + + Description of success from the user's point of view. + + diff --git a/ccm-portalserver/doc/use-cases/psrv-00610.xml b/ccm-portalserver/doc/use-cases/psrv-00610.xml new file mode 100644 index 000000000..05dc67c4b --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00610.xml @@ -0,0 +1,19 @@ + + + + + Navigate to a Personal Portal + + + + + + + + + Basic path for the use case + + + Description of success from the user's point of view. + + diff --git a/ccm-portalserver/doc/use-cases/psrv-00710.xml b/ccm-portalserver/doc/use-cases/psrv-00710.xml new file mode 100644 index 000000000..c712db320 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00710.xml @@ -0,0 +1,54 @@ + + + + + View Help for the Current System Page + + + + + + + + + + +This is a subfunction use case for the View Help summary use case (PSRV-00010).

    + +

    The Portal Participant can open a Help page for any page in the Armenta system.

    + +

    From this page, the WP has access to the complete Help system.

    + + ]]> +
    + + + + + The WP participant is viewing an Armenta page.

    + + ]]> +
    + +

    + +

    +

      +
    1. The WP selects the action to view Help for the current page.
    2. +
    3. The system displays a Help page with procedures for using the current Armenta page.
    4. +
    +

    + + + ]]> +
    + + The System simultaneously displays the necessary Help page and the page it documents.

    + + ]]> +
    +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00730.xml b/ccm-portalserver/doc/use-cases/psrv-00730.xml new file mode 100644 index 000000000..327152812 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00730.xml @@ -0,0 +1,74 @@ + + + + + Navigate Help Using a Table of Contents + + + + + + + + +

    + +

    This is a subfunction use case for the View Help summary use case (PSRV-00710).

    + +

    From any Help page, the Portal Participant can view Help information organized in a traditional table of contents format. In addition, the WP can quickly move to the appropriate Help files from the table of contents.

    + + ]]> +
    + + + + + The WP participant is viewing a Help page.

    + + ]]> +
    + +

    + +

    +

      +
    1. The WP selects the action to view the Help table of contents page.
    2. +
    3. The system displays the Help table of contents page.
    4. +
    5. The WP chooses a Help topic to view.
    6. +
    7. The system displays the selected Help topic.
    8. +
    +

    + + ]]> +
    + + The system simultaneously displays the original Armenta page and the Help page that was requested from the Help table of contents page.

    + + ]]> +
    + + None

    + + ]]> +
    + + None

    + + + ]]> +
    + + None +

    + + + ]]> +
    +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00740.xml b/ccm-portalserver/doc/use-cases/psrv-00740.xml new file mode 100644 index 000000000..b6a11aaea --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00740.xml @@ -0,0 +1,67 @@ + + + + + Search Help Using a Keyword + + + + + + + + +

    + +

    This is a subfunction use case for the View Help summary use case (PSRV-00710).

    + +

    The Portal Participant can search the complete set of Help pages for those pages that have been associated with a specific keyword.

    + +

    Note: This capability does not have the priority to be completed for version 1. It will be included in version 2.

    + + ]]> +
    + + + + + The WP participant is viewing a Help page.

    + + ]]> +
    + +

    + +

    +

      +
    1. The WP selects the action to search Help by keywords.
    2. +
    3. The system displays the Keyword Search page.
    4. +
    5. The WP enters a keyword or phrase and initiates the search.
    6. +
    7. The system displays a results page with the list of Help pages associated with the keyword.
    8. +
    9. The WP chooses a Help topic to view.
    10. +
    11. The system displays the selected Help topic.
    12. +
    +

    + + ]]> +
    + + The system simultaneously displays the Armenta page from which Help was initiated and a Help page that is associated with the keywords used for the search.

    + + ]]> +
    + +

    + +
      +
    1. If there are no Help pages associated with the keywords, the system displays a message indicating that there are no Help pages associated with the specified keywords.
    2. +
    + + ]]> +
    +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00750.xml b/ccm-portalserver/doc/use-cases/psrv-00750.xml new file mode 100644 index 000000000..db49fe9e0 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00750.xml @@ -0,0 +1,66 @@ + + + + + Search Help Using a Text String + + + + + + + +

    + +

    This is a subfunction use case for the View Help summary use case (PSRV-00710).

    + +

    The Portal Participant can perform a full-text search of the complete set of Help pages to find those pages that include a specified text string.

    + +

    Note: This capability does not have the priority to be completed for version 1. It will be included in version 2.

    + + ]]> +
    + + + + + The WP participant is viewing a Help page.

    + + ]]> +
    + +

    + +

    +

      +
    1. The WP selects the action to do a full-text search of Help.
    2. +
    3. The system displays the Full Text Search page.
    4. +
    5. The WP enters a text string and initiates the search.
    6. +
    7. The system displays a results page with the list of Help pages that include the text string.
    8. +
    9. The WP chooses a Help topic to view.
    10. +
    11. The system displays the selected Help topic.
    12. +
    +

    + + ]]> +
    + + The system simultaneously displays the Armenta page from which Help was initiated and a Help page that includes the specified text sting.

    + + ]]> +
    + +

    + +
      +
    1. If no Help pages contain the text string, the system displays a message indicating that no Help pages contain the text string.
    2. +
    + + ]]> +
    +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00810.xml b/ccm-portalserver/doc/use-cases/psrv-00810.xml new file mode 100644 index 000000000..0ab681084 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00810.xml @@ -0,0 +1,108 @@ + + + + + Browsing Bookmarks within a Portal + + + + + +This Use case is the Base Case for Bookmark functionality. General Bookmark +attributes and procedures are detailed here. +

    +
    +The Collaborative Portal bookmarking model has one important distinction from browser bookmarking: In CW, Bookmarks can be shared. In a Collaborative +Portal, the bookmark portlet is available for reading and use in most cases, by all participants. The ability to create a bookmark and have it appear within the bookmark portlet for a particular portal, is controlled by write privelage on the bookmark portlet.

    +
    +

    +A system user may have participant status in many different portals, including their own personal portal. When using a collaborative portal or an application associated with a collaborative portal, the bookmark portlet +instanced by that portal only shows bookmarks associated with that portal. +When a user is at his or her own personal portal, the Bookmark portlet can be configured to show just personal bookmarks, or import bookmarks as read/use only from collaborative portals that include the user as a member. +

    + + ]]> +
    + + + + + +This Use Case pre-supposes that the Bookmark portlet is present in the portal, and that it has at least one bookmark saved there. +

    + + ]]> +
    + +
    +
      +
    1. The portal participant chooses a bookmark entry from the bookmark portlet.
    2. +
    3. The participant is taken to that content item.
    4. +
    +

    + + ]]> +
    + + +

    + + ]]> +
    + + +The portal participant arrives at the desired content destination. +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + +

    + + ]]> +
    + +
    +

    + + + + + ]]> +
    + +Focused + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00820.xml b/ccm-portalserver/doc/use-cases/psrv-00820.xml new file mode 100644 index 000000000..a11103774 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00820.xml @@ -0,0 +1,106 @@ + + + + + Adding a Bookmark + + + + + +This Use Case addresses the need to add a bookmark to the bookmarks portlet. +

    + + ]]> +
    + + + + + +This Use Case requires that the Participant have write privelage on the Bookmark Portlet application. +

    + + ]]> +
    + +
    +
      +
    1. During the course of browsing content within a portal, a participant wishes to bookmark an item for quick retrieval later.
    2. +
    3. The Participant clicks the "Add Bookmark" icon at the top of the portal to store the location of the content item in the bookmark portlet. +
    +

    + + ]]> +
    + + +

    + + ]]> +
    + + +A link to the knowledge item appears in the Bookmarks portlet. +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + +

    + + ]]> +
    + +
    +
      +
    • Why are CW bookmarks better than browser bookmarks? Because they can be shared?
    • +
    • What action does a user take to save a bookmark? A "Save Bookmark" button? Should this be a persistent feature of the portal UI?
    • +
    • What if the item that a user wishes to bookmark is within a portal +application, and the nav bar, help, and other ancillary links (where a +'save bookmark' button would probably be located) are not present? Does +this imply that every (reasonable) application that populates the portal, needs to incorporate a "Bookmark This View" button in it UI?
    • +
    +

    + + + + + ]]> +
    + +Facade. + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00830.xml b/ccm-portalserver/doc/use-cases/psrv-00830.xml new file mode 100644 index 000000000..690b36da1 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00830.xml @@ -0,0 +1,111 @@ + + + + + Editing Bookmark Properties + + + + + +This Use Case describes the action of modifying the properties of an existing bookmark. +

    + + ]]> +
    + + + + + +This Use Case requires these three pre-conditions: +
      +
    1. The bookmark portlet is present in the portal.
    2. +
    3. At least one bookmark has been saved in the portlet.
    4. +
    5. The participant has write privilege on the bookmark application instance for this portal.
    6. +
    + +

    + + ]]> +
    + +
    +
    1. Through the bookmark portlet, the participant launches the bookmark application.
    2. +
    3. The bookmark application lists all bookmarks for that portal (and within the personal portal, all bookmarks available in collaborative portals that the user participates in, if desired...)
    4. +
    5. The user then selects a bookmark
    6. +
    7. After a bookmark has been selected, A form is displayed with all pertinent information about the bookmark, such as:
    8. +
      • Creation date
      • +
      • The name of the person who created it.
      • +
      • The name of the bookmark (A modifiable field)
      • +
      • The target URL (A modifiable field)
      • +
      • The name of the portal it is associated with
      • +
      • A link that says Delete This Bookmark
      +
    9. The user can change the name or the target of the bookmark, by modifying +the values in the modifiable field, then press the save button
    10. + +
    +

    + + ]]> +
    + + +

    + + ]]> +
    + + +The desired property is modified. +

    + + ]]> +
    + + +If properties are opened up for a bookmark that the participant does NOT have write privileges, then the properties are displayed as unmodifiable fields (i.e., labels instead of text fields). + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + +

    + +

    Open Issues:
    +

    + + + + + ]]> +
    + +Focused + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00840.xml b/ccm-portalserver/doc/use-cases/psrv-00840.xml new file mode 100644 index 000000000..5fa410f6a --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00840.xml @@ -0,0 +1,98 @@ + + + + + Deleting a Bookmark + + + + + +This Use Case addresses the need to occasionally remove a bookmark from the bookmark portlet. +

    + + ]]> +
    + + + + + +This Use case requires the Participant to have write/delete privelage on +the Bookmarks application/Portlet for this portal. +

    + + ]]> +
    + +
    +
      +
    1. The participant clicks the "edit bookmarks" icon on the bookmarks portlet/
    2. +
    3. The Participant clicks the "delete bookmark" link next to the bookmark to be deleted. +
    +

    + + ]]> +
    + + +

    + + ]]> +
    + + +The link to the knowledge item is removed from the Bookmarks portlet. +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + + +

    + + ]]> +
    + + +

    + + ]]> +
    + +
    +

    + + + + ]]> +
    + +Focused + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00900.xml b/ccm-portalserver/doc/use-cases/psrv-00900.xml new file mode 100644 index 000000000..830fbc270 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00900.xml @@ -0,0 +1,48 @@ + + + + + Select a Theme for a Portal + + + + + + + + + + + + +
  • The PA selects the 'Configure Portal' link.
  • +
  • The PA then selects the 'Themes' tab on the portal configuration page.
  • +
  • A list of available themes is displayed with check boxes next to them. The portals current theme has the checkbox next to it pre-selected. In addition, a thumbnail of the look and feel for the currently selected theme is displayed
  • +
  • The PA selects the desired theme, and the thumbnail changes to reflect this selection. This step may iterate...
  • +
  • After finalizing on a theme, the PA clicks the 'Save Theme' button
  • +
  • The PA is returned to the Configure Portal layout tab.
  • + + ]]> +
    + + +
  • AP 1: The PA chooses not to change the theme, and clicks the cancel button, then is returned to the configure portal layout tab.
  • +
  • AP 2: The PA is not satisfied with any of the themes offered and clicks the 'Create Theme' button. This path is detailed in PSRV-00910:Create A Theme for a Portal
  • + ]]> +
    + + + + + + + The desired theme is now used to render the portal. + + Filled +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00910.xml b/ccm-portalserver/doc/use-cases/psrv-00910.xml new file mode 100644 index 000000000..9951b2dbf --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00910.xml @@ -0,0 +1,28 @@ + + + + + Create a Theme for a Portal + + + + + + + + + +
  • The PA clicks the 'Create Theme' button on the Themes tab in the Configure Portal area
  • +
  • The PA is taken to the theme creation page
  • +
  • The currently selected theme is pre-loaded into the UI, so that PA's can easily make incremental changes.
  • +
  • The PA creates the theme. Individual aspects of this process are detailed in use cases psrv-00950 through psrv-00970
  • +
  • When satisfied, the PA clicks the 'Save Theme' button.
  • +
  • The UI prompts the PA for a name for the theme. After entering one, the PA clicks 'Save' and the PA is returned to the Configure Portal Themes tab, where the new theme appears in the list.
  • + + ]]> +
    + + Description of success from the user's point of view. + +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00951.xml b/ccm-portalserver/doc/use-cases/psrv-00951.xml new file mode 100644 index 000000000..126f6260b --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00951.xml @@ -0,0 +1,23 @@ + + + + + Set Context Bar Color for Theme + + + + + + + + +
  • User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  • +
  • User locates section of Create Theme form for Context bar and either selects one of the preset colors, or enters a custom value.
  • + + ]]> +
    + + +Focused +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00952.xml b/ccm-portalserver/doc/use-cases/psrv-00952.xml new file mode 100644 index 000000000..204b81c60 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00952.xml @@ -0,0 +1,23 @@ + + + + + Set Active Tab Color for Theme + + + + + + + + +
  • User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  • +
  • User locates section of Create Theme form for Active Tab and either selects one of the preset colors, or enters a custom value.
  • + + ]]> +
    + + +Focused +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00953.xml b/ccm-portalserver/doc/use-cases/psrv-00953.xml new file mode 100644 index 000000000..7aa7acd7e --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00953.xml @@ -0,0 +1,23 @@ + + + + + Set Inactive Tab Color for Theme + + + + + + + + +
  • User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  • +
  • User locates section of Create Theme form for Inactive Tab and either selects one of the preset colors, or enters a custom value.
  • + + ]]> +
    + + +Focused +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00954.xml b/ccm-portalserver/doc/use-cases/psrv-00954.xml new file mode 100644 index 000000000..dba4ec94a --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00954.xml @@ -0,0 +1,23 @@ + + + + + Set Active Tab Text Color for Theme + + + + + + + + +
  • User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  • +
  • User locates section of Create Theme form for Active Tab Text Color and either selects one of the preset colors, or enters a custom value.
  • + + ]]> +
    + + +Focused +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00955.xml b/ccm-portalserver/doc/use-cases/psrv-00955.xml new file mode 100644 index 000000000..c73dd51de --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00955.xml @@ -0,0 +1,24 @@ + + + + + Set Inactive Tab Text Color for Theme + + + + + + + + + +
  • User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  • +
  • User locates section of Create Theme form for Inactive Tab Text and either selects one of the preset colors, or enters a custom value.
  • + + ]]> +
    + + +Focused +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00956.xml b/ccm-portalserver/doc/use-cases/psrv-00956.xml new file mode 100644 index 000000000..bdbfa25be --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00956.xml @@ -0,0 +1,24 @@ + + + + + Set Top Rule Under Tabs Color for Theme + + + + + + + + + +
  • User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  • +
  • User locates section of Create Theme form for Top Rule Under Tabs and either selects one of the preset colors, or enters a custom value.
  • + + ]]> +
    + + +Focused +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00957.xml b/ccm-portalserver/doc/use-cases/psrv-00957.xml new file mode 100644 index 000000000..e51c71c34 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00957.xml @@ -0,0 +1,23 @@ + + + + + Set Top Rule No Tabs Color for Theme + + + + + + + + +
  • User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  • +
  • User locates section of Create Theme form for Top Rule No Tabs and either selects one of the preset colors, or enters a custom value.
  • + + ]]> +
    + + +Focused +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00958.xml b/ccm-portalserver/doc/use-cases/psrv-00958.xml new file mode 100644 index 000000000..c28630c71 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00958.xml @@ -0,0 +1,23 @@ + + + + + Set Bottom Rule Color for Theme + + + + + + + + +
  • User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  • +
  • User locates section of Create Theme form for Bottom Rule and either selects one of the preset colors, or enters a custom value.
  • + + ]]> +
    + + +Focused +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00959.xml b/ccm-portalserver/doc/use-cases/psrv-00959.xml new file mode 100644 index 000000000..1547fd7d2 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00959.xml @@ -0,0 +1,23 @@ + + + + + Set Portlet Header Color for Theme + + + + + + + + +
  • User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  • +
  • User locates section of Create Theme form for Context bar and either selects one of the preset colors, or enters a custom value.
  • + + ]]> +
    + + +Focused +
    diff --git a/ccm-portalserver/doc/use-cases/psrv-00960.xml b/ccm-portalserver/doc/use-cases/psrv-00960.xml new file mode 100644 index 000000000..3155272ae --- /dev/null +++ b/ccm-portalserver/doc/use-cases/psrv-00960.xml @@ -0,0 +1,24 @@ + + + + + Set Portlet Icon Color for Theme + + + + + + + + + +
  • User begins on Create Theme page (see PSRV-00910:Create a Theme for a Portal)
  • +
  • User locates section of Create Theme form for PortletIcon and either selects one of the preset colors, or enters a custom value.
  • + + ]]> +
    + + +Focused +
    diff --git a/ccm-portalserver/doc/use-cases/use-case.dtd b/ccm-portalserver/doc/use-cases/use-case.dtd new file mode 100644 index 000000000..2e5c46b29 --- /dev/null +++ b/ccm-portalserver/doc/use-cases/use-case.dtd @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ccm-portalserver/etc/enterprise.init.in b/ccm-portalserver/etc/enterprise.init.in new file mode 100644 index 000000000..f317ca826 --- /dev/null +++ b/ccm-portalserver/etc/enterprise.init.in @@ -0,0 +1,48 @@ +// Red Hat Enterprise Portal Server initialization file +// +// When running Portal Server, the parameters for +// com.arsdigita.kernel.Initializer must be modified. +// +// ::login-stylesheet:: -> login_ps_en.xsl +// ::subsite-dispatcher-class:: -> com.arsdigita.portalserver.pslogin.PSSubsiteDispatcher + +init com.arsdigita.portalserver.Initializer { } + +init com.arsdigita.portalserver.admin.Initializer { } + +init com.arsdigita.portalserver.ui.admin.Initializer { } + +init com.arsdigita.portalserver.personal.Initializer { } + +// init com.arsdigita.populate.portalserver.Initializer { +// //Set baseStringSeed to a non-empty value +// //to make all generated Strings in params +// //deterministic rather than random. This will +// //allow you to populate the same values across +// //multiple runs on clean databases. +// baseStringSeed = ""; +// numUsers = 5; +// numPortalSiteLevels = 2; +// numPortalSitesPerLevel = 2; +// populateAppPairs = { +// //populateForum args: numPosts, numMsgs per post +// { "com.arsdigita.forum.PopulateForum", {3, 5}}, +// //populateDocmgr args: numFolderLevels, numFolders, numFiles +// { "com.arsdigita.docmgr.PopulateDocmgr", {3, 2, 2}}, +// //populateFaq args: numQuestions +// { "com.arsdigita.faq.PopulateFaq", {5}}, +// //populateGlossary args: numWords +// { "com.arsdigita.glossary.PopulateGlossary", {5}}, +// //populateBookmarks args: numBookmarks +// { "com.arsdigita.bookmarks.PopulateBookmarks", {5}} +// }; +// populatePortlets = { +// "com.arsdigita.portlets.freeform.PopulateFreeformPortlet", +// "com.arsdigita.portlets.timeofday.PopulateTimeOfDayPortlet", +// "com.arsdigita.portlets.rssfeed.PopulateRSSFeedPortlet", +// "com.arsdigita.populate.portlets.PopulateApplicationDirectoryPortlet", +// "com.arsdigita.populate.portlets.PopulatePortalNavigatorPortlet", +// "com.arsdigita.populate.portlets.PopulatePortalSummaryPortlet", +// "com.arsdigita.populate.portlets.PopulateMyPortalsPortlet" +// }; +// } diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/ApplicationDirectory.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/ApplicationDirectory.pdl new file mode 100644 index 000000000..77a61f542 --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/ApplicationDirectory.pdl @@ -0,0 +1,27 @@ +// +// Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// @author Justin Ross (justin@arsdigita.com) +// $Id: ApplicationDirectory.pdl pboy $ +// $DateTime: 2004/08/17 23:19:25 $ +model com.arsdigita.workspace; + +import com.arsdigita.portal.Portlet; + +object type ApplicationDirectoryPortlet extends Portlet { + // Nothing goes here. +} diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/JunkPortlet.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/JunkPortlet.pdl new file mode 100644 index 000000000..464f3ffa7 --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/JunkPortlet.pdl @@ -0,0 +1,38 @@ +// +// Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// $Id: //portalserver/dev/pdl/com/arsdigita/portalserver/JunkPortlet.pdl#3 $ +// $DateTime: 2004/08/17 23:19:25 $ +model com.arsdigita.workspace.misc; + +import com.arsdigita.portal.Portlet; + +// This PDL file contains the PDL for "junk portlets." A junk +// portlet, as coined by Richard Buck, is a portlet that is for +// learning about building portlets or building something not +// related to the final product. +// +// @author Bryan Quinn (bquinn@arsdigita.com) +// @version $Id: //portalserver/dev/pdl/com/arsdigita/portalserver/JunkPortlet.pdl#3 $ + +// The StarfleetPortlet establishes communications with the +// the United Federation of Planets. +// +// @author Bryan Quinn (bquinn@arsdigita.com) +// @version 1.0 + +object type StarfleetPortlet extends Portlet { } diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/Role.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/Role.pdl new file mode 100644 index 000000000..b68dba563 --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/Role.pdl @@ -0,0 +1,39 @@ +// +// Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// $Id: Role.pdl pboy $ + +model com.arsdigita.workspace; + +import com.arsdigita.kernel.Group; + +object type Role extends Group { + String[1..1] roleName = ps_workspace_roles.role_name VARCHAR(100); + String[1..1] assigneeTitle = ps_workspace_roles.assignee_title VARCHAR(100); + String[0..1] description = ps_workspace_roles.description VARCHAR(4000); + Boolean[1..1] isSystem = ps_workspace_roles.is_system CHAR(1); + String[0..1] type = ps_workspace_roles.type VARCHAR(100); + + reference key (ps_workspace_roles.role_id); +} + +association { + Workspace[1..1] workspace = + join ps_workspace_roles.workspace_id to ps_workspaces.workspace_id; + component Role[0..n] roles = + join ps_workspaces.workspace_id to ps_workspace_roles.workspace_id; +} diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/SubWorkspaceTab.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/SubWorkspaceTab.pdl new file mode 100644 index 000000000..c2ba96123 --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/SubWorkspaceTab.pdl @@ -0,0 +1,35 @@ +// +// Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// @author Jim Parsons (jparsons@redhat.com) +// $Id: SubWorkspaceTab.pdl pboy $ +model com.arsdigita.workspace; + +import com.arsdigita.workspace.WorkspaceTab; + + +object type SubWorkspaceTab extends WorkspaceTab { + + reference key (ps_sub_workspace_tabs.tab_id); +} + +association { + WorkspaceTab[1..1] workspaceTab = + join ps_sub_workspace_tabs.super_tab_id to ps_workspace_tabs.tab_id; + SubWorkspaceTab[0..n] subWorkspaceTab = + join ps_workspace_tabs.tab_id to ps_sub_workspace_tabs.super_tab_id; +} diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/Theme.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/Theme.pdl new file mode 100644 index 000000000..196ae6f27 --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/Theme.pdl @@ -0,0 +1,53 @@ +// +// Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// @author Jim Parsons (jparsons@arsdigita.com) +// $Id: //portalserver/dev/pdl/com/arsdigita/portalserver/Theme.pdl#4 $ +// $DateTime: 2004/08/17 23:19:25 $ +model com.arsdigita.workspace; + +import com.arsdigita.kernel.ACSObject; +import com.arsdigita.web.Application; + + +object type ThemeApplication extends Application { + reference key (ps_themeapplications.theme_app_id); +} + +object type Theme extends ACSObject { + String[0..1] theme_name = ps_themes.theme_name VARCHAR(4000); + String[0..1] theme_desc = ps_themes.theme_desc VARCHAR(4000); + String[0..1] ctx_bar_color = ps_themes.ctx_bar_color VARCHAR(100); + String[0..1] ctx_bar_text_color = ps_themes.ctx_bar_text_color VARCHAR(100); + String[0..1] active_tab_color = ps_themes.active_tab_color VARCHAR(100); + String[0..1] active_tab_text_color = ps_themes.active_tab_text_color VARCHAR(100); + String[0..1] inactive_tab_color = ps_themes.inactive_tab_color VARCHAR(100); + String[0..1] inactive_tab_text_color = ps_themes.inactive_tab_text_color VARCHAR(100); + String[0..1] top_rule = ps_themes.top_rule VARCHAR(100); + String[0..1] bottom_rule = ps_themes.bottom_rule VARCHAR(100); + String[0..1] portlet_head = ps_themes.portlet_head VARCHAR(100); + String[0..1] portlet_icon = ps_themes.portlet_icon VARCHAR(100); + String[0..1] portlet_border_color = ps_themes.portlet_border_color VARCHAR(100); + String[0..1] portlet_border_style = ps_themes.portlet_border_style VARCHAR(100); + String[0..1] portlet_header_text_color = ps_themes.portlet_header_text_color VARCHAR(100); + String[0..1] page_bg_color = ps_themes.page_bg_color VARCHAR(100); + String[0..1] page_bg_image = ps_themes.page_bg_image VARCHAR(100); + String[0..1] narrow_bg_color = ps_themes.narrow_bg_color VARCHAR(100); + String[0..1] body_text_color = ps_themes.body_text_color VARCHAR(100); + + reference key (ps_themes.theme_id); +} diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/Workspace.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/Workspace.pdl new file mode 100644 index 000000000..b369e5e71 --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/Workspace.pdl @@ -0,0 +1,284 @@ +// +// Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// @author Justin Ross (justin@arsdigita.com) +// $Id: Workspace.pdl pboy $ +model com.arsdigita.workspace; + +import com.arsdigita.portal.Portal; +import com.arsdigita.kernel.User; +import com.arsdigita.web.Application; +import com.arsdigita.kernel.Group; +import com.arsdigita.kernel.Party; + + +object type Workspace extends Application { + Boolean isReady = ps_workspaces.ready_p CHAR(1); + Boolean isArchived = ps_workspaces.archive_p CHAR(1); + Boolean isDraft = ps_workspaces.draft_p CHAR(1); + Boolean isPersonalizable = ps_workspaces.personalizable_p CHAR(1); + Boolean isSubPortal = ps_workspaces.subportal_p CHAR(1); + Date[0..1] creationDate = ps_workspaces.creation_date DATE; + Date[0..1] archiveDate = ps_workspaces.archive_date DATE; + String mission = ps_workspaces.mission VARCHAR(4000); + Theme[0..1] theme = join ps_workspaces.theme_id to ps_themes.theme_id; + Workspace[0..n] relatedWorkspace = + join ps_workspaces.workspace_id + to ps_workspace_workspace_map.referencing_workspace_id, + join ps_workspace_workspace_map.referenced_workspace_id + to ps_workspaces.workspace_id; + + reference key (ps_workspaces.workspace_id); +} + +association { + Workspace[0..n] workspaces = + join parties.party_id to ps_workspace_participant_map.participant_id, + join ps_workspace_participant_map.workspace_id to ps_workspaces.workspace_id; + Party[0..n] participants = + join ps_workspaces.workspace_id to ps_workspace_participant_map.workspace_id, + join ps_workspace_participant_map.participant_id to parties.party_id; +} + +query childWorkspacesForApplicationID { + Workspace workspace; + + do { + select + acs_objects.object_id, + acs_objects.object_type, + acs_objects.display_name, + acs_objects.default_domain_class, + applications.parent_application_id, + applications.package_id, + applications.title, + applications.description, + applications.primary_url, + ps_workspaces.ready_p, + ps_workspaces.archive_p, + ps_workspaces.mission + from + acs_objects, + applications, + ps_workspaces + where + applications.parent_application_id = :applicationID + -- joins + and acs_objects.object_id = applications.application_id + and applications.application_id = ps_workspaces.workspace_id + } map { + workspace.id = acs_objects.object_id; + workspace.objectType = acs_objects.object_type; + workspace.displayName = acs_objects.display_name; + workspace.defaultDomainClass = acs_objects.default_domain_class; + workspace.parentResource.id = applications.parent_application_id; + workspace.packageInstance.id = applications.package_id; + workspace.title = applications.title; + workspace.description = applications.description; + workspace.primaryURL = applications.primary_url; + workspace.isReady = ps_workspaces.ready_p; + workspace.isArchived = ps_workspaces.archive_p; + workspace.mission = ps_workspaces.mission; + } +} + +query rootWorkspaces { + Workspace workspace; + + do { + select + acs_objects.object_id, + acs_objects.object_type, + acs_objects.display_name, + acs_objects.default_domain_class, + applications.parent_application_id, + applications.package_id, + applications.title, + applications.description, + applications.primary_url, + ps_workspaces.ready_p, + ps_workspaces.archive_p, + ps_workspaces.mission + from + acs_objects, + applications, + ps_workspaces + where + (applications.parent_application_id is null or + parent_application_id = :parentID) + -- joins + and acs_objects.object_id = applications.application_id + and applications.application_id = ps_workspaces.workspace_id + } map { + workspace.id = acs_objects.object_id; + workspace.objectType = acs_objects.object_type; + workspace.displayName = acs_objects.display_name; + workspace.defaultDomainClass = acs_objects.default_domain_class; + workspace.parentResource.id = applications.parent_application_id; + workspace.packageInstance.id = applications.package_id; + workspace.title = applications.title; + workspace.description = applications.description; + workspace.primaryURL = applications.primary_url; + workspace.isReady = ps_workspaces.ready_p; + workspace.isArchived = ps_workspaces.archive_p; + workspace.mission = ps_workspaces.mission; + } +} + +query workspaceForSiteNodeID { + Workspace workspace; + + do { + select + acs_objects.object_id, + acs_objects.object_type, + acs_objects.display_name, + acs_objects.default_domain_class, + applications.parent_application_id, + applications.package_id, + applications.title, + applications.description, + applications.primary_url, + ps_workspaces.ready_p, + ps_workspaces.mission + from + site_nodes, + apm_packages, + applications, + acs_objects, + ps_workspaces + where + site_nodes.node_id = :siteNodeID + -- joins + and site_nodes.object_id = apm_packages.package_id + and apm_packages.package_id = applications.package_id + and applications.application_id = acs_objects.object_id + and applications.application_id = ps_workspaces.workspace_id + } map { + workspace.id = acs_objects.object_id; + workspace.objectType = acs_objects.object_type; + workspace.displayName = acs_objects.display_name; + workspace.defaultDomainClass = acs_objects.default_domain_class; + workspace.parentResource.id = applications.parent_application_id; + workspace.packageInstance.id = applications.package_id; + workspace.title = applications.title; + workspace.description = applications.description; + workspace.primaryURL = applications.primary_url; + workspace.isReady = ps_workspaces.ready_p; + workspace.mission = ps_workspaces.mission; + } +} + +query RolesForUser { + BigDecimal groupID; + do { + select group_id + from group_member_trans_map + where member_id = :participantID + } map { + groupID = group_id; + } +} + +query RolesForGroup { + BigDecimal groupID; + do { + select group_id + from group_subgroup_trans_map + where subgroup_id = :participantID and group_id != subgroup_id + } map { + groupID = group_id; + } +} + +query DirectRolesForUser { + BigDecimal groupID; + do { + select group_id + from group_member_map + where member_id = :participantID + } map { + groupID = group_id; + } +} + +query DirectRolesForGroup { + BigDecimal groupID; + do { + select group_id + from group_subgroup_map + where subgroup_id = :participantID + } map { + groupID = group_id; + } +} + + +query WorkspaceParticipantsWithInitial { + BigDecimal participantID; + do { + select wpm.participant_id as participant_id + from ps_workspace_participant_map wpm, person_names pn, users u + where wpm.workspace_id = :workspaceID and + wpm.participant_id = u.user_id and + u.name_id = pn.name_id and + upper(substr(pn.family_name, 1, 1)) = :nameInitial + UNION ALL + select wpm.participant_id as participant_id + from ps_workspace_participant_map wpm, groups g + where wpm.workspace_id = :workspaceID and + wpm.participant_id = g.group_id and + upper(substr(g.name, 1, 1)) = :nameInitial + } map { + participantID = participant_id; + } +} + + +query WorkspaceParticipantInitials { + String initial; + do { + select name_initial + from ( select distinct upper(substr(pn.family_name, 1, 1)) + as name_initial + from ps_workspace_participant_map wpm, person_names pn, users u + where wpm.workspace_id = :workspaceID and + wpm.participant_id = u.user_id and + u.name_id = pn.name_id + UNION + select distinct upper(substr(g.name, 1, 1)) as name_initial + from ps_workspace_participant_map wpm, groups g + where wpm.workspace_id = :workspaceID and + wpm.participant_id = g.group_id ) + order by name_initial + } map { + initial = name_initial; + } +} + + +query WorkspaceParticipantIDs { + BigDecimal id; + do { + select wpm.participant_id + from ps_workspace_participant_map wpm + where wpm.workspace_id = :workspaceID + } map { + id = wpm.participant_id; + } +} + diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/WorkspaceNavigator.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/WorkspaceNavigator.pdl new file mode 100644 index 000000000..eabae3475 --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/WorkspaceNavigator.pdl @@ -0,0 +1,29 @@ +// +// Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// $Id: WorkspaceNavigator.pdl pboy $ + +model com.arsdigita.workspace; + +import com.arsdigita.portal.Portlet; + +// @author Justin Ross (justin@arsdigita.com) +// @version $Id: WorkspaceNavigator.pdl pboy $ + +object type WorkspaceNavigatorPortlet extends Portlet { + // Nothing goes here. +} diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/WorkspaceSummary.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/WorkspaceSummary.pdl new file mode 100644 index 000000000..394325bd7 --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/WorkspaceSummary.pdl @@ -0,0 +1,29 @@ +// +// Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// $Id: WorkspaceSummary.pdl pboy $ + +model com.arsdigita.workspace; + +import com.arsdigita.portal.Portlet; + +// @author Justin Ross (justin@arsdigita.com) +// @version $Id: WorkspaceSummary.pdl pboy $ + +object type WorkspaceSummaryPortlet extends Portlet { + // Nothing goes here. +} diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/WorkspaceTab.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/WorkspaceTab.pdl new file mode 100644 index 000000000..3f427a7fd --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/WorkspaceTab.pdl @@ -0,0 +1,38 @@ +// +// Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// $Id: WorkspaceTab.pdl pboy $ + +model com.arsdigita.workspace; + +import com.arsdigita.portal.Portal; + +// @author Jim Parsons (jparsons@arsdigita.com) + +object type WorkspaceTab extends Portal { + Integer sortKey = ps_workspace_tabs.sort_key INTEGER; + String tab_layout = ps_workspace_tabs.layout VARCHAR(100); + + reference key (ps_workspace_tabs.tab_id); +} + +association { + Workspace[1..1] workspace = + join ps_workspace_tabs.workspace_id to ps_workspaces.workspace_id; + component WorkspaceTab[0..n] workspaceTab = + join ps_workspaces.workspace_id to ps_workspace_tabs.workspace_id; +} diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/admin/PSAdmin.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/admin/PSAdmin.pdl new file mode 100644 index 000000000..51c3ae1f2 --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/admin/PSAdmin.pdl @@ -0,0 +1,24 @@ +// +// Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// $Id: PSAdmin.pdl pboy $ + +model com.arsdigita.admin; + +import com.arsdigita.web.Application; + +object type CWAdmin extends Application { } diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/personal-workspace/MyWorkspacesPortlet.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/personal-workspace/MyWorkspacesPortlet.pdl new file mode 100644 index 000000000..3399a7c20 --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/personal-workspace/MyWorkspacesPortlet.pdl @@ -0,0 +1,70 @@ +// +// Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// $Id: MyWorkspacesPortlet.pdl pboy $ + +model com.arsdigita.workspace.personal; + +import com.arsdigita.portal.Portlet; + +object type MyWorkspacesPortlet extends Portlet { + // Left empty. +} + +query MyWorkspaces { + BigDecimal id; + String title; + String primaryURL; + + do { + select distinct + a.application_id, + a.title, + a.primary_url, + upper(a.title) as sort_key + from + group_member_trans_index gmti, + ps_workspace_participant_map wpm, + applications a + where + gmti.member_id = :userID + -- joins + and gmti.group_id = wpm.participant_id + and wpm.workspace_id = a.application_id + union + select + a.application_id, + a.title, + a.primary_url, + upper(a.title) as sort_key + from + ps_workspace_participant_map wpm, + applications a + where + wpm.participant_id = :userID + -- leave out his or her personal workspace + and wpm.workspace_id <> :personalWorkspaceID + -- joins + and wpm.workspace_id = a.application_id + order by + sort_key + } map { + id = a.application_id; + title = a.title; + primaryURL = a.primary_url; + } +} diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/personal-workspace/PersonalWorkspace.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/personal-workspace/PersonalWorkspace.pdl new file mode 100644 index 000000000..6343324b9 --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/personal-workspace/PersonalWorkspace.pdl @@ -0,0 +1,44 @@ +// +// Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// $Id: PersonalWorkspace.pdl pboy $ + +model com.arsdigita.workspace.personal; + +import com.arsdigita.workspace.Workspace; +import com.arsdigita.web.Application; +import com.arsdigita.portal.Portal; +import com.arsdigita.kernel.User; + +// @author Justin Ross (justin@arsdigita.com) +// @version $Id: PersonalWorkspace.pdl pboy $ + +object type PersonalWorkspace extends Workspace { + reference key (ps_personal_workspaces.personal_workspace_id); + + aggressive load (user.id); +} + +association { + User[1..1] user = join ps_personal_workspaces.user_id to users.user_id; + PersonalWorkspace[0..1] personalWorkspace + = join users.user_id to ps_personal_workspaces.user_id; +} + +object type PersonalWorkspaceCreator extends Application { + // This page intentionally left blank. +} diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/query-RolesWithCounts.ora.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/query-RolesWithCounts.ora.pdl new file mode 100644 index 000000000..96182aed8 --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/query-RolesWithCounts.ora.pdl @@ -0,0 +1,40 @@ +// +// Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// $Id: //portalserver/dev/pdl/com/arsdigita/portalserver/query-RolesWithCounts.ora.pdl#2 $ +// $DateTime: 2004/08/17 23:19:25 $ +model com.arsdigita.workspace; + +query RolesWithCounts { + String roleName; + Integer roleCount; + do { + select role_name, + ((select count(*) + from group_member_map + where group_id = roles.role_id) + + (select count(*) + from group_subgroup_map + where group_id = roles.role_id and group_id != subgroup_id)) + role_count + from workspace_roles roles + where workspace_id = :workspaceID + } map { + roleName = role_name; + roleCount = role_count; + } +} \ No newline at end of file diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/query-RolesWithCounts.pg.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/query-RolesWithCounts.pg.pdl new file mode 100644 index 000000000..fcbcbadf9 --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/query-RolesWithCounts.pg.pdl @@ -0,0 +1,44 @@ +// +// Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// $Id: //portalserver/dev/pdl/com/arsdigita/portalserver/query-RolesWithCounts.pg.pdl#2 $ +// $DateTime: 2004/08/17 23:19:25 $ +model com.arsdigita.workspace; + +query RolesWithCounts { + String roleName; + Integer roleCount; + do { + select role_name, count(*) as role_count + from + (select group_id, member_id, role_name + from group_member_map gmm, workspace_roles roles + where gmm.group_id = roles.role_id + and workspace_id = :workspaceID + union + select group_id, subgroup_id as member_id, role_name + from group_subgroup_map gsm, workspace_roles roles + where gsm.group_id = roles.role_id + and gsm.group_id != gsm.subgroup_id + and workspace_id = :workspaceID + ) count_view + group by role_name + } map { + roleName = role_name; + roleCount = role_count; + } +} diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/query-SubPortalPortlets.ora.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/query-SubPortalPortlets.ora.pdl new file mode 100644 index 000000000..156f032f9 --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/query-SubPortalPortlets.ora.pdl @@ -0,0 +1,45 @@ +// +// Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// $Id: //portalserver/dev/pdl/com/arsdigita/portalserver/query-SubPortalPortlets.ora.pdl#2 $ +// $DateTime: 2004/08/17 23:19:25 $ +model com.arsdigita.workspace; + +import com.arsdigita.portal.Portlet; + +query getSubPortalPortlets { + Portlet portlet; + do { + select p.portlet_id, p.portal_id + from portlets p + where p.portal_id = :subPortalTabID + UNION ALL + select p.portlet_id, p.portal_id + from portlets p, + portals i, + applications a, + sub_workspace_tabs s + where s.tab_id = :subPortalTabID + and i.portal_id = s.super_tab_id + and a.application_id = p.portlet_id + and a.cell_number in :cells + } map { + portlet.id = p.portlet_id; + portlet.portal.id = p.portal_id; + } +} + diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/query-SubPortalPortlets.pg.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/query-SubPortalPortlets.pg.pdl new file mode 100644 index 000000000..39094c08a --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/query-SubPortalPortlets.pg.pdl @@ -0,0 +1,45 @@ +// +// Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// $Id: //portalserver/dev/pdl/com/arsdigita/portalserver/query-SubPortalPortlets.pg.pdl#2 $ +// $DateTime: 2004/08/17 23:19:25 $ +model com.arsdigita.workspace; + +import com.arsdigita.portal.Portlet; + +query getSubPortalPortlets { + Portlet portlet; + do { + select p.portlet_id, p.portal_id + from portlets p + where p.portal_id = :subPortalTabID + UNION ALL + select p.portlet_id, p.portal_id + from portlets p, + portals i, + applications a, + sub_workspace_tabs s + where s.tab_id = :subPortalTabID + and i.portal_id = s.super_tab_id + and a.application_id = p.portlet_id + and a.cell_number = :cell + } map { + portlet.id = p.portlet_id; + portlet.portal.id = p.portal_id; + } +} + diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/workspace-ui/PortalArchiver.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/workspace-ui/PortalArchiver.pdl new file mode 100644 index 000000000..729878180 --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/workspace-ui/PortalArchiver.pdl @@ -0,0 +1,25 @@ +// +// Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// $Id: PortalArchiver.pdl pboy $ + +model com.arsdigita.workspace.ui; + +import com.arsdigita.workspace.*; +import com.arsdigita.web.Application; + +object type PortalArchiver extends Application {} diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/workspace-ui/PortalSiteMap.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/workspace-ui/PortalSiteMap.pdl new file mode 100644 index 000000000..82b7d3181 --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/workspace-ui/PortalSiteMap.pdl @@ -0,0 +1,25 @@ +// +// Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// $Id: PortalSiteMap.pdl pboy $ + +model com.arsdigita.workspace.ui; + +import com.arsdigita.workspace.*; +import com.arsdigita.web.Application; + +object type PortalSiteMap extends Application {} diff --git a/ccm-portalserver/pdl/com/arsdigita/portalserver/workspace-ui/WorkspaceCreator.pdl b/ccm-portalserver/pdl/com/arsdigita/portalserver/workspace-ui/WorkspaceCreator.pdl new file mode 100644 index 000000000..0bfdd2be0 --- /dev/null +++ b/ccm-portalserver/pdl/com/arsdigita/portalserver/workspace-ui/WorkspaceCreator.pdl @@ -0,0 +1,25 @@ +// +// Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// $Id: WorkspaceCreator.pdl pboy $ + +model com.arsdigita.workspace.ui; + +import com.arsdigita.workspace.*; +import com.arsdigita.web.Application; + +object type WorkspaceCreator extends Application {} diff --git a/ccm-portalserver/sql/ccm-portalserver/default/index-personal_workspaces_usr_id_idx.sql b/ccm-portalserver/sql/ccm-portalserver/default/index-personal_workspaces_usr_id_idx.sql new file mode 100644 index 000000000..94650daa3 --- /dev/null +++ b/ccm-portalserver/sql/ccm-portalserver/default/index-personal_workspaces_usr_id_idx.sql @@ -0,0 +1,21 @@ +-- +-- Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +-- +-- This library is free software; you can redistribute it and/or +-- modify it under the terms of the GNU Lesser General Public License +-- as published by the Free Software Foundation; either version 2.1 of +-- the License, or (at your option) any later version. +-- +-- This library is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public +-- License along with this library; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-- +-- $Id: index-personal_workspaces_usr_id_idx.sql pboy $ + + +create index ps_personal_workspaces_usr_id_idx on ps_personal_workspaces(user_id); diff --git a/ccm-portalserver/sql/ccm-portalserver/default/index-workspace_roles_workspc_id_idx.sql b/ccm-portalserver/sql/ccm-portalserver/default/index-workspace_roles_workspc_id_idx.sql new file mode 100644 index 000000000..64ed33f62 --- /dev/null +++ b/ccm-portalserver/sql/ccm-portalserver/default/index-workspace_roles_workspc_id_idx.sql @@ -0,0 +1,21 @@ +-- +-- Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +-- +-- This library is free software; you can redistribute it and/or +-- modify it under the terms of the GNU Lesser General Public License +-- as published by the Free Software Foundation; either version 2.1 of +-- the License, or (at your option) any later version. +-- +-- This library is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public +-- License along with this library; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-- +-- $Id: index-workspace_roles_workspc_id_idx.sql pboy $ +-- $DateTime: 2004/08/17 23:19:25 $ + +create index ps_workspace_roles_workspc_id_idx on ps_workspace_roles(workspace_id); diff --git a/ccm-portalserver/sql/ccm-portalserver/default/index-workspace_tabs_workspac_id_idx.sql b/ccm-portalserver/sql/ccm-portalserver/default/index-workspace_tabs_workspac_id_idx.sql new file mode 100644 index 000000000..941ec57d0 --- /dev/null +++ b/ccm-portalserver/sql/ccm-portalserver/default/index-workspace_tabs_workspac_id_idx.sql @@ -0,0 +1,21 @@ +-- +-- Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +-- +-- This library is free software; you can redistribute it and/or +-- modify it under the terms of the GNU Lesser General Public License +-- as published by the Free Software Foundation; either version 2.1 of +-- the License, or (at your option) any later version. +-- +-- This library is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public +-- License along with this library; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-- +-- $Id: index-workspace_tabs_workspac_id_idx.sql pboy $ +-- $DateTime: 2004/08/17 23:19:25 $ + +create index ps_workspace_tabs_workspac_id_idx on ps_workspace_tabs(workspace_id); diff --git a/ccm-portalserver/sql/ccm-portalserver/default/index-workspaces_theme_id_idx.sql b/ccm-portalserver/sql/ccm-portalserver/default/index-workspaces_theme_id_idx.sql new file mode 100644 index 000000000..05b3cfaa5 --- /dev/null +++ b/ccm-portalserver/sql/ccm-portalserver/default/index-workspaces_theme_id_idx.sql @@ -0,0 +1,21 @@ +-- +-- Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +-- +-- This library is free software; you can redistribute it and/or +-- modify it under the terms of the GNU Lesser General Public License +-- as published by the Free Software Foundation; either version 2.1 of +-- the License, or (at your option) any later version. +-- +-- This library is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public +-- License along with this library; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-- +-- $Id: index-workspaces_theme_id_idx.sql pboy $ +-- $DateTime: 2004/08/17 23:19:25 $ + +create index ps_workspaces_theme_id_idx on ps_workspaces(theme_id); diff --git a/ccm-portalserver/sql/ccm-portalserver/default/index-wrkspc_prtcpnt_mp_wrksp_id_idx.sql b/ccm-portalserver/sql/ccm-portalserver/default/index-wrkspc_prtcpnt_mp_wrksp_id_idx.sql new file mode 100644 index 000000000..35c897776 --- /dev/null +++ b/ccm-portalserver/sql/ccm-portalserver/default/index-wrkspc_prtcpnt_mp_wrksp_id_idx.sql @@ -0,0 +1,22 @@ +-- +-- Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +-- +-- This library is free software; you can redistribute it and/or +-- modify it under the terms of the GNU Lesser General Public License +-- as published by the Free Software Foundation; either version 2.1 of +-- the License, or (at your option) any later version. +-- +-- This library is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public +-- License along with this library; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-- +-- $Id: index-wrkspc_prtcpnt_mp_wrksp_id_idx.sql pboy $ +-- $DateTime: 2004/08/17 23:19:25 $ + +create index ps_wrkspc_prtcpnt_mp_wrksp_id_idx + on ps_workspace_participant_map(workspace_id); diff --git a/ccm-portalserver/sql/ccm-portalserver/default/index-wrkspc_wrkspc_mp_rfrn_wrks_idx.sql b/ccm-portalserver/sql/ccm-portalserver/default/index-wrkspc_wrkspc_mp_rfrn_wrks_idx.sql new file mode 100644 index 000000000..278d342c6 --- /dev/null +++ b/ccm-portalserver/sql/ccm-portalserver/default/index-wrkspc_wrkspc_mp_rfrn_wrks_idx.sql @@ -0,0 +1,22 @@ +-- +-- Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +-- +-- This library is free software; you can redistribute it and/or +-- modify it under the terms of the GNU Lesser General Public License +-- as published by the Free Software Foundation; either version 2.1 of +-- the License, or (at your option) any later version. +-- +-- This library is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public +-- License along with this library; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-- +-- $Id: index-wrkspc_wrkspc_mp_rfrn_wrks_idx.sql pboy $ +-- $DateTime: 2004/08/17 23:19:25 $ + +create index ps_wrkspc_wrkspc_mp_rfrn_wrks_idx + on ps_workspace_workspace_map(referenced_workspace_id); diff --git a/ccm-portalserver/sql/ccm-portalserver/oracle-se-create.sql b/ccm-portalserver/sql/ccm-portalserver/oracle-se-create.sql new file mode 100644 index 000000000..c4da61fdb --- /dev/null +++ b/ccm-portalserver/sql/ccm-portalserver/oracle-se-create.sql @@ -0,0 +1,31 @@ +-- +-- Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +-- +-- This library is free software; you can redistribute it and/or +-- modify it under the terms of the GNU Lesser General Public License +-- as published by the Free Software Foundation; either version 2.1 of +-- the License, or (at your option) any later version. +-- +-- This library is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public +-- License along with this library; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-- +-- $Id: //portalserver/dev/sql/ccm-portalserver/oracle-se-create.sql#2 $ +-- $DateTime: 2004/08/17 23:19:25 $ + + +@@ ddl/oracle-se/create.sql + +@@ default/index-personal_workspaces_usr_id_idx.sql +@@ default/index-workspace_roles_workspc_id_idx.sql +@@ default/index-workspaces_theme_id_idx.sql +@@ default/index-workspace_tabs_workspac_id_idx.sql +@@ default/index-wrkspc_prtcpnt_mp_wrksp_id_idx.sql +@@ default/index-wrkspc_wrkspc_mp_rfrn_wrks_idx.sql + +@@ ddl/oracle-se/deferred.sql diff --git a/ccm-portalserver/sql/ccm-portalserver/postgres-create.sql b/ccm-portalserver/sql/ccm-portalserver/postgres-create.sql new file mode 100644 index 000000000..43440d504 --- /dev/null +++ b/ccm-portalserver/sql/ccm-portalserver/postgres-create.sql @@ -0,0 +1,34 @@ +-- +-- Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +-- +-- This library is free software; you can redistribute it and/or +-- modify it under the terms of the GNU Lesser General Public License +-- as published by the Free Software Foundation; either version 2.1 of +-- the License, or (at your option) any later version. +-- +-- This library is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public +-- License along with this library; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-- +-- $Id: //portalserver/dev/sql/ccm-portalserver/postgres-create.sql#2 $ +-- $DateTime: 2004/08/17 23:19:25 $ + +begin; + +\i ddl/postgres/create.sql + +\i default/index-personal_workspaces_usr_id_idx.sql +\i default/index-workspace_roles_workspc_id_idx.sql +\i default/index-workspaces_theme_id_idx.sql +\i default/index-workspace_tabs_workspac_id_idx.sql +\i default/index-wrkspc_prtcpnt_mp_wrksp_id_idx.sql +\i default/index-wrkspc_wrkspc_mp_rfrn_wrks_idx.sql + +\i ddl/postgres/deferred.sql + +commit; diff --git a/ccm-portalserver/sql/ccm-portalserver/upgrade/deleteme/upgrade_change_theme_name.sql b/ccm-portalserver/sql/ccm-portalserver/upgrade/deleteme/upgrade_change_theme_name.sql new file mode 100644 index 000000000..96bfb9255 --- /dev/null +++ b/ccm-portalserver/sql/ccm-portalserver/upgrade/deleteme/upgrade_change_theme_name.sql @@ -0,0 +1,22 @@ +-- +-- Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +-- +-- This library is free software; you can redistribute it and/or +-- modify it under the terms of the GNU Lesser General Public License +-- as published by the Free Software Foundation; either version 2.1 of +-- the License, or (at your option) any later version. +-- +-- This library is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public +-- License along with this library; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-- +-- $Id: //portalserver/dev/sql/ccm-portalserver/upgrade/upgrade_change_theme_name.sql#2 $ +-- $DateTime: 2004/08/17 23:19:25 $ + +update themes set page_bg_image = '/assets/cw/backgrounds/stars.gif' where theme_name = 'Stars and Stripes'; +update themes set theme_name = 'Stars and Bars' where theme_name = 'Stars and Stripes'; diff --git a/ccm-portalserver/sql/ccm-portalserver/upgrade/deleteme/upgrade_is_archived.sql b/ccm-portalserver/sql/ccm-portalserver/upgrade/deleteme/upgrade_is_archived.sql new file mode 100644 index 000000000..8f6425220 --- /dev/null +++ b/ccm-portalserver/sql/ccm-portalserver/upgrade/deleteme/upgrade_is_archived.sql @@ -0,0 +1,22 @@ +-- +-- Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +-- +-- This library is free software; you can redistribute it and/or +-- modify it under the terms of the GNU Lesser General Public License +-- as published by the Free Software Foundation; either version 2.1 of +-- the License, or (at your option) any later version. +-- +-- This library is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public +-- License along with this library; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-- +-- $Id: //portalserver/dev/sql/ccm-portalserver/upgrade/upgrade_is_archived.sql#2 $ +-- $DateTime: 2004/08/17 23:19:25 $ + +alter table workspaces add column (archive_p CHAR(1)); +update workspaces set archive_p = '0'; diff --git a/ccm-portalserver/sql/ccm-portalserver/upgrade/deleteme/upgrade_is_personal_is_draft.sql b/ccm-portalserver/sql/ccm-portalserver/upgrade/deleteme/upgrade_is_personal_is_draft.sql new file mode 100644 index 000000000..f1bbeba1f --- /dev/null +++ b/ccm-portalserver/sql/ccm-portalserver/upgrade/deleteme/upgrade_is_personal_is_draft.sql @@ -0,0 +1,24 @@ +-- +-- Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +-- +-- This library is free software; you can redistribute it and/or +-- modify it under the terms of the GNU Lesser General Public License +-- as published by the Free Software Foundation; either version 2.1 of +-- the License, or (at your option) any later version. +-- +-- This library is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public +-- License along with this library; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-- +-- $Id: //portalserver/dev/sql/ccm-portalserver/upgrade/upgrade_is_personal_is_draft.sql#2 $ +-- $DateTime: 2004/08/17 23:19:25 $ + +alter table workspaces add (draft_p CHAR(1)); +update workspaces set draft_p = '0'; +alter table workspaces add (personalizable_p CHAR(1)); +update workspaces set personalizable_p = '0'; diff --git a/ccm-portalserver/sql/ccm-portalserver/upgrade/deleteme/upgrade_is_subportal.sql b/ccm-portalserver/sql/ccm-portalserver/upgrade/deleteme/upgrade_is_subportal.sql new file mode 100644 index 000000000..2a6b90492 --- /dev/null +++ b/ccm-portalserver/sql/ccm-portalserver/upgrade/deleteme/upgrade_is_subportal.sql @@ -0,0 +1,22 @@ +-- +-- Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. +-- +-- This library is free software; you can redistribute it and/or +-- modify it under the terms of the GNU Lesser General Public License +-- as published by the Free Software Foundation; either version 2.1 of +-- the License, or (at your option) any later version. +-- +-- This library is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public +-- License along with this library; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-- +-- $Id: //portalserver/dev/sql/ccm-portalserver/upgrade/upgrade_is_subportal.sql#2 $ +-- $DateTime: 2004/08/17 23:19:25 $ + +alter table workspaces add (subportal_p CHAR(1)); +update workspaces set subportal_p = '0'; diff --git a/ccm-portalserver/src/ccm-portalserver.config b/ccm-portalserver/src/ccm-portalserver.config new file mode 100644 index 000000000..adfdba100 --- /dev/null +++ b/ccm-portalserver/src/ccm-portalserver.config @@ -0,0 +1,4 @@ + + + + diff --git a/ccm-portalserver/src/ccm-portalserver.load b/ccm-portalserver/src/ccm-portalserver.load new file mode 100644 index 000000000..467dc613e --- /dev/null +++ b/ccm-portalserver/src/ccm-portalserver.load @@ -0,0 +1,15 @@ + + + +
    + + + +
    + + + + + + + diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ApplicationAuthenticationListener.java b/ccm-portalserver/src/com/arsdigita/portalserver/ApplicationAuthenticationListener.java new file mode 100644 index 000000000..3b58571f9 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ApplicationAuthenticationListener.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.event.RequestEvent; +import com.arsdigita.bebop.event.RequestListener; + +import com.arsdigita.dispatcher.AccessDeniedException; + + +import com.arsdigita.web.Application; +import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.permissions.PermissionDescriptor; +import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; + + +import com.arsdigita.ui.login.UserAuthenticationListener; + +import java.io.IOException; +import org.apache.log4j.Logger; + +/** + * A RequestListener that verifies the user + * has a given privilege on the current Application. + * + * The user is redirected to ACCESS_DENIED if their is + * insufficient permission. + * + * XXX Permissions will be incorporated in December. This is + * temporary for use in our engineering production server until. + * that time. + * + * @param privilegeName a String that represents the privlege name for the + * privilege a user must have to see the page. + * + */ +public class ApplicationAuthenticationListener + extends UserAuthenticationListener implements RequestListener { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ApplicationAuthenticationListener.java#5 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static final Logger s_log = Logger.getLogger + (ApplicationAuthenticationListener.class); + + private String m_privilegeName; + + public ApplicationAuthenticationListener(String privilegeName) { + super(); + m_privilegeName = privilegeName; + } + + public void setRequiredPrivilege(String privilegeName) { + m_privilegeName = privilegeName; + } + + public String getRequiredPrivilege() { + return m_privilegeName; + } + + /** + * Checks whether the user is logged in. If not, redirects the client + * to the login page. + **/ + public void pageRequested(RequestEvent event) { + PageState state = event.getPageState(); + + PrivilegeDescriptor privDescriptor = + PrivilegeDescriptor.get(m_privilegeName); + + PermissionDescriptor permDescriptor = new PermissionDescriptor + (privDescriptor, + Application.getCurrentApplication(state.getRequest()), + Kernel.getContext().getParty()); + + if (!PermissionService.checkPermission(permDescriptor)) { + denyRequest(state); + } + + } + + /** + * Action performed if authentication failed. Override this to + * perform a perform a specific action after the authentication + * check. + */ + public void denyRequest(PageState state) { + if (Kernel.getContext().getParty() == null) { + Util.redirectToLoginPage(state); + return; + } + + throw new AccessDeniedException(); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ApplicationDirectoryPortlet.java b/ccm-portalserver/src/com/arsdigita/portalserver/ApplicationDirectoryPortlet.java new file mode 100644 index 000000000..53f2ebaee --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ApplicationDirectoryPortlet.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.web.ApplicationCollection; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.portal.apportlet.AppPortlet; +import com.arsdigita.bebop.portal.AbstractPortletRenderer; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.GridPanel; +import com.arsdigita.xml.Element; + +public class ApplicationDirectoryPortlet extends AppPortlet { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ApplicationDirectoryPortlet.java#7 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + public static final String BASE_DATA_OBJECT_TYPE = + "com.arsdigita.workspace.ApplicationDirectoryPortlet"; + + protected String getBaseDataObjectType() { + return BASE_DATA_OBJECT_TYPE; + } + + public ApplicationDirectoryPortlet(DataObject dataObject) { + super(dataObject); + } + + protected AbstractPortletRenderer doGetPortletRenderer() { + return new ApplicationDirectoryPortletRenderer(this); + } +} + +class ApplicationDirectoryPortletRenderer extends AbstractPortletRenderer { + private ApplicationDirectoryPortlet m_portlet; + + public ApplicationDirectoryPortletRenderer + (ApplicationDirectoryPortlet portlet) { + m_portlet = portlet; + } + + protected void generateBodyXML(PageState pageState, Element parentElement) { + PortalSite portalsite = + PortalSite.getPortalSiteForAppPortlet(m_portlet); + + if (portalsite == null) { + return; + } + + // Variables used cursorwise. + int counter; + String title = null; + String url = null; + + ApplicationCollection apps = + portalsite.getFullPagePortalSiteApplications(); + + GridPanel innerPanel = new GridPanel(1); + + for (counter = 0; apps.next(); counter++) { + title = apps.getTitle(); + url = apps.getPrimaryURL(); + innerPanel.add(new Link(title, url)); + } + + if (counter == 0) { + innerPanel.add(new Label(GlobalizationUtil.globalize("cw.workspace.none"))); + } + + innerPanel.generateXML(pageState, parentElement); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ApplicationPage.java b/ccm-portalserver/src/com/arsdigita/portalserver/ApplicationPage.java new file mode 100644 index 000000000..a72d11e50 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ApplicationPage.java @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.bebop.Container; +import com.arsdigita.bebop.DimensionalNavbar; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Container; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.bebop.event.PrintEvent; +import com.arsdigita.bebop.DimensionalNavbar; + +import com.arsdigita.web.Application; +import com.arsdigita.kernel.Party; +import com.arsdigita.kernel.Kernel; + +import com.arsdigita.util.Assert; + + + + + +/** + * ApplicationPage class + * + * This is a common page to be used by all applications for consistent + * styling. + * + * @author Tracy Adams + * @version $Revision: #6 $ $Date: 2004/08/17 $ + */ + +/* XXX Have to control links with permissions and + * add access control + */ +public class ApplicationPage extends CWPage { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ApplicationPage.java#6 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static org.apache.log4j.Logger log = + org.apache.log4j.Logger.getLogger(ApplicationPage.class.getName()); + + protected ApplicationPage() { + this(true); + } + + protected ApplicationPage(boolean checkPermission) { + if (checkPermission) { + // XXX Right now, we restrict this page to users with read + // access on the current application. + addRequestListener(new ApplicationAuthenticationListener("read")); + } + } + + public void lock() { + buildPage(); + + super.lock(); + } + + // Only the PortalPage.lock() should invoke this + // method, though users of this class may sometimes want to + // override this method. + protected final void buildPage() { + buildTitle(); + buildContextBar(); + buildGlobal(getGlobal()); + buildHeader(getHeader()); + buildBody(getBody()); + buildFooter(getFooter()); + } + + protected void buildTitle() { + setTitle(new Label(new CurrentApplicationLabelPrinter())); + } + + protected void buildContextBar() { + DimensionalNavbar navbar = new DimensionalNavbar(); + + navbar.setClassAttr("portalNavbar"); + + navbar.add(new Link(new CurrentApplicationLinkPrinter())); + + getHeader().add(navbar); + } + + protected void buildGlobal(Container global) { + Link link = new Link( new Label(GlobalizationUtil.globalize("cw.workspace.sign_out")), "/register/logout"); + + link.setClassAttr("signoutLink"); + + getGlobal().add(link); + } + + protected void buildHeader(Container header) { + // Nothing yet + } + + protected void buildBody(Container body) { + // Nothing by default + } + + protected void buildFooter(Container footer) { + // Nothing by default + } + + + // + // Classes for use in generating dynamic labels and links + // + + protected class PersonalPortalLinkPrinter implements PrintListener { + public PersonalPortalLinkPrinter() { + // Empty + } + + public void prepare(PrintEvent e) { + Link link = (Link) e.getTarget(); + + Party party = Kernel.getContext().getParty(); + + // Assert.assertNotNull(party, "Party party"); + Assert.exists(party, "Party party"); + + link.setChild(new Label(GlobalizationUtil.globalize("cw.workspace.personal_workspace"))); + link.setTarget("/personal-portal/" + party.getID() + "/"); + } + } + + // No need for a PersonalPortalLabelPrinter...yet. + + protected class CurrentApplicationLinkPrinter implements PrintListener { + public CurrentApplicationLinkPrinter() { + // Empty + } + + public void prepare(PrintEvent e) { + Link link = (Link) e.getTarget(); + PageState pageState = e.getPageState(); + + Application app = Application.getCurrentApplication + (pageState.getRequest()); + + Assert.exists(app, "Application app"); + + link.setChild(new Label(app.getTitle())); + link.setTarget(app.getPrimaryURL()); + } + } + + protected class CurrentApplicationLabelPrinter implements PrintListener { + public CurrentApplicationLabelPrinter() { + // Empty + } + + public void prepare(PrintEvent e) { + Label label = (Label) e.getTarget(); + PageState pageState = e.getPageState(); + + Application app = Application.getCurrentApplication + (pageState.getRequest()); + + Assert.exists(app, "Application app"); + + label.setLabel(app.getTitle()); + } + } + + protected class ParentApplicationLinkPrinter implements PrintListener { + public ParentApplicationLinkPrinter() { + // Empty + } + + public void prepare(PrintEvent e) { + Link link = (Link) e.getTarget(); + PageState pageState = e.getPageState(); + + Application app = Application.getCurrentApplication + (pageState.getRequest()); + + Assert.exists(app, "Application app"); + + Application parent = app.getParentApplication(); + + link.setChild(new Label(parent.getTitle())); + link.setTarget(parent.getPrimaryURL()); + } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/CWPage.java b/ccm-portalserver/src/com/arsdigita/portalserver/CWPage.java new file mode 100644 index 000000000..6090ff77e --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/CWPage.java @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.Container; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.parameters.IntegerParameter; + +import com.arsdigita.util.Assert; + +import com.arsdigita.xml.Element; + +import org.apache.log4j.Logger; + +/** + * CWPage class + * + * This is a common page to be used by all CW pages for consistent + * styling. + * + * @author Eric Lorenzo + * @version $Revision: #5 $ $Date: 2004/08/17 $ + */ + +/* XXX Have to control links with permissions and + * add access control + */ +public class CWPage extends Page { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/CWPage.java#5 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static final Logger s_log = Logger.getLogger(CWPage.class); + + private final Container m_global; + private final Container m_header; + private final Container m_body; + private final Container m_footer; + + private IntegerParameter m_selected = new IntegerParameter("m"); + + public static final String PORTAL_GLOBAL_ELEMENT = "portalserver:global"; + public static final String PORTAL_HEADER_ELEMENT = "portalserver:header"; + public static final String PORTAL_BODY_ELEMENT = "portalserver:body"; + public static final String PORTAL_FOOTER_ELEMENT = "portalserver:footer"; + public static final String PORTAL_XML_NS = + "http://www.redhat.com/portalserver/1.0"; + + protected CWPage() { + super(new Label(), new SimpleContainer()); + + setClassAttr("portalserver"); + + m_panel = new Panel(); + + addGlobalStateParam(m_selected); + + m_global = new SimpleContainer + (PORTAL_GLOBAL_ELEMENT, PORTAL_XML_NS); + m_header = new SimpleContainer + (PORTAL_HEADER_ELEMENT, PORTAL_XML_NS); + m_body = new SimpleContainer + (PORTAL_BODY_ELEMENT, PORTAL_XML_NS); + m_footer = new SimpleContainer + (PORTAL_FOOTER_ELEMENT, PORTAL_XML_NS); + + super.add(m_global); + super.add(m_header); + super.add(m_body); + super.add(m_footer); + } + + /** + * Makes the given component the only visible component between + * the header and footer of this page. + */ + public void goModal(PageState ps, Component c) { + Component old = getSelected(ps); + if (old != null) { + old.setVisible(ps, false); + } + c.setVisible(ps, true); + setSelected(ps, c); + } + + private Component getSelected(PageState ps) { + Integer stateIndex = (Integer) ps.getValue(m_selected); + Component c = null; + if (stateIndex != null) { + c = getComponent(stateIndex.intValue()); + } + + return c; + } + + private void setSelected(PageState ps, Component c) { + if (c == null) { + ps.setValue(m_selected, null); + } else { + ps.setValue(m_selected, new Integer(stateIndex(c))); + } + } + + /** + * Clears the currently selected modal component if it has been set. + */ + public void goUnmodal(PageState ps) { + Component old = getSelected(ps); + if (old != null) { + old.setVisible(ps, false); + } + setSelected(ps, null); + } + + private class Panel extends SimpleContainer { + public void generateXML(PageState ps, Element p) { + Component selected = getSelected(ps); + if (selected == null) { + super.generateXML(ps, p); + } else { + SimpleContainer fakeBody = + new SimpleContainer(PORTAL_BODY_ELEMENT, + PORTAL_XML_NS); + fakeBody.add(selected); + + Element parent = generateParent(p); + + m_header.generateXML(ps, parent); + fakeBody.generateXML(ps, parent); + m_footer.generateXML(ps, parent); + } + } + } + + /** + * Adds a component to the body. + * + * @param pc the component to be added + */ + public void add(Component pc) { + // Assert.assertNotLocked(this); + Assert.isUnlocked(this); + m_body.add(pc); + } + + public Container getGlobal() { + return m_global; + } + + public Container getHeader() { + return m_header; + } + + public Container getBody() { + return m_body; + } + + public Container getFooter() { + return m_footer; + } + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/CWURLFinder.java b/ccm-portalserver/src/com/arsdigita/portalserver/CWURLFinder.java new file mode 100644 index 000000000..73e141ed8 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/CWURLFinder.java @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.web.*; +import com.arsdigita.persistence.*; +import com.arsdigita.persistence.metadata.*; +import com.arsdigita.domain.*; +import com.arsdigita.kernel.*; +import java.util.*; +import java.net.URLEncoder; +import javax.servlet.http.HttpUtils; + +/** + * Experimental + * + * A URLFinder that can be registered for most object types. The + * CWURLFinder is constructed with a specified URL pattern such + * as one-ticket?ticket_id=:id. + * + * @author Oumi Mehrotra (oumi@arsdigita.com) + * @version $Id: CWURLFinder.java $ + **/ +public class CWURLFinder implements URLFinder { + + private String m_base; + private Map m_params; + + /** + * Constructor + * @param urlEndingPattern + */ + public CWURLFinder(String urlEndingPattern) { + m_params = new HashMap(); + m_base = parseQueryString(urlEndingPattern, m_params); + // setFormat(urlEndingPattern); + } + + public String find(OID oid, String context) throws NoValidURLException { + return find(oid); + } + + public String find(OID oid) throws NoValidURLException { + ACSObject obj; + + try { + obj = (ACSObject) DomainObjectFactory.newInstance(oid); + } catch (DataObjectNotFoundException e) { + throw new NoValidURLException("No such data object: " + oid); + } + + if (obj instanceof Application) { + return ((Application) obj).getPrimaryURL(); + } else { + Application app = Application.getContainingApplication(obj); + if (app == null) { + throw new NoValidURLException( + "Could not find application instance for " + obj); + } + return app.getPrimaryURL() + m_base + unparseQueryString(oid); + } + } + + /** + * Copied from com.arsdigita.util.URLRewriter and modified slightly. + **/ + private String unparseQueryString(OID oid) { + StringBuffer buf = new StringBuffer(128); + char sep = '?'; + Iterator keys = m_params.keySet().iterator(); + while (keys.hasNext()) { + String key = (String)keys.next(); + Object value = m_params.get(key); + if (value instanceof String[]) { + String[] values = (String[])value; + for (int i = 0; i < values.length; i++) { + if (values[i] != null) { + appendParam(buf, sep, key, getValue(oid, values[i])); + sep = '&'; + } + } + continue; + } else if (value != null) { + appendParam(buf, sep, key, getValue(oid, value.toString())); + sep = '&'; + } + } + return buf.toString(); + } + + private String getValue(OID oid, String val) { + if (val.equals(":oid")) { + return oid.toString(); + } else if (val.charAt(0)==':') { + return oid.get(val.substring(1)).toString(); + } + return val; + } + + // + // COPIED FROM: com.arsdigita.util.URLRewriter + // + + private static String parseQueryString(String url, Map params) { + int qmark = url.indexOf('?'); + if (qmark < 0) { + return url; + } + String base = url.substring(0, qmark); + String query = url.substring(qmark+1); + params.putAll(HttpUtils.parseQueryString(query)); + return base; + } + + /** + * Appends string representation of a parameter to the given + * StringBuffer: sep + URLEncode(key) + '=' + URLEncode(value) + **/ + private static void appendParam(StringBuffer buf, char sep, + String key, String value) { + buf.append(sep).append(URLEncoder.encode(key)) + .append('=').append(URLEncoder.encode(value)); + } + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ColorPicker.java b/ccm-portalserver/src/com/arsdigita/portalserver/ColorPicker.java new file mode 100644 index 000000000..c49b1d0c7 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ColorPicker.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + +import com.arsdigita.bebop.FormSection; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.form.TextField; +import com.arsdigita.bebop.form.RadioGroup; +import com.arsdigita.bebop.form.Option; +import com.arsdigita.bebop.Label; + +/** + * This class represents a drop-in FormSection for color selection. + * The class includes a title label describing what the color refers to, + * a radiogroup for the color choices, and a text input field for + * use when the available pallette does not include a desired color. + * Note: All color values are represented within the class + * by strings of the type "#FFCA04". Neither the input on + * the text field, or the addColor method are checked for proper format + * - care must be taken by the user to maintain the proper string + * representation. + * + *

    The ColorPicker class includes a built in default group + * of 12 colors. If the developer would rather supply their + * own colors, clearColors() can be called, and then the + * internal radioGroup populated with colors provided by a + * radioGroup using the addOptionGroup() method. + * + *

    The getValue() method for this class checks first if + * the text field is null. If not, its value is returned. If null, + * the radiogroup is then checked for its value and returned. + * + * @author Jim Parsons + */ + +public class ColorPicker extends FormSection { + + TextField m_textfield; + Label m_label; + RadioGroup m_grp; + String m_name; + + static final String BLACK = "#000000"; + static final String DARKGRAY = "#A9A9A9"; + static final String LIGHTGRAY = "#D3D3D3"; + static final String BLUE = "#0000FF"; + static final String CYAN = "#00FFFF"; + static final String GREEN = "#00FF00"; + static final String MAGENTA = "#FF00FF"; + static final String RED = "#FF0000"; + static final String ORANGE = "#FFA500"; + static final String PINK = "#FFC0CB"; + static final String YELLOW = "#FFFF00"; + static final String WHITE = "#FFFFFF"; + + public ColorPicker(String name) { + + this(name, "#000000"); + + } + + public ColorPicker(String name, String defaultValue) { + + + super.setClassAttr("colorpicker"); + + //Remove pesky white spaces + String cleanName = name.replace(' ', '_'); + + m_grp = new RadioGroup(cleanName); + m_grp.setClassAttr("colorchoices"); + m_grp.clearOptions(); + + m_grp.addOption(new Option(BLACK,"1")); + m_grp.addOption(new Option(DARKGRAY,"2")); + m_grp.addOption(new Option(LIGHTGRAY,"3")); + m_grp.addOption(new Option(BLUE,"4")); + m_grp.addOption(new Option(CYAN, "5")); + m_grp.addOption(new Option(GREEN,"6")); + m_grp.addOption(new Option(MAGENTA,"7")); + m_grp.addOption(new Option(RED,"8")); + m_grp.addOption(new Option(ORANGE,"9")); + m_grp.addOption(new Option(PINK,"10")); + m_grp.addOption(new Option(YELLOW,"11")); + m_grp.addOption(new Option(WHITE,"12")); + + m_label = new Label(name); + m_name = name; + m_textfield = new TextField("Colorpicker_" + cleanName); + m_textfield.setDefaultValue(""); + add(m_label); + add(m_textfield); + add(m_grp); + + } + + public String getValue(PageState ps) { + String rgroup = null; + rgroup = (String)m_grp.getValue(ps); + + if(rgroup == null) { + return (String)m_textfield.getValue(ps); + } + else { + return(rgroup); + } + } + + void setValue(PageState ps, String val) { + m_textfield.setValue(ps,val); + } + + public void clearColors() { + m_grp.clearOptions(); + } + + public void addOptionGroup(RadioGroup rgroup) { + m_grp = rgroup; + } + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ECMPresentationManager.java.nolongerInUse b/ccm-portalserver/src/com/arsdigita/portalserver/ECMPresentationManager.java.nolongerInUse new file mode 100644 index 000000000..29f060c3e --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ECMPresentationManager.java.nolongerInUse @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + +import com.arsdigita.bebop.page.PageTransformer; +import com.arsdigita.persistence.*; +import com.arsdigita.kernel.*; +import com.arsdigita.sitenode.*; +import com.arsdigita.web.*; +import java.util.*; + +/** + * ECMPresentationManager + * + * @author rhs@mit.edu + * @version $Revision: #5 $ $Date: 2004/08/17 $ + * @version $Id: ECMPresentationManager.java pboy $ + **/ + +public class ECMPresentationManager extends PageTransformer { + + + private static Map m_sheets = new HashMap(); + + protected synchronized Stylesheet findStylesheet(SiteNode node, Locale l, + String outputType) { + TransactionContext ctx = + SessionManager.getSession().getTransactionContext(); + + boolean commit = false; + if (!ctx.inTxn()) { + ctx.beginTxn(); + commit = true; + } + + String key = l + "." + outputType; + + Stylesheet result = (Stylesheet) m_sheets.get(key); + + if (result == null || !result.isValid()) { + ApplicationType type = + ApplicationType.retrieveApplicationTypeForApplication( + PortalSite.BASE_DATA_OBJECT_TYPE); + PackageType pkg = type.getPackageType(); + result = pkg.getStylesheet(l, outputType); + result.disconnect(); + m_sheets.put(key, result); + } + + if (commit) { + ctx.commitTxn(); + } + + return result; + } + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/Icons.java b/ccm-portalserver/src/com/arsdigita/portalserver/Icons.java new file mode 100644 index 000000000..fc863d1d9 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/Icons.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + + +import com.arsdigita.bebop.Image; + +/** + * This class contains Images for the various CW icons. These image + * instances are all locked, so they may not be directly added to a + * page's static structure -- instead, they must be cloned. However, + * they can be used within a list or table cell renderer. + **/ +public class Icons { + + + public static final Image USER_16; + public static final Image GROUP_16; + public static final Image LEFT_16; + public static final Image RIGHT_16; + public static final Image UP_16; + public static final Image DOWN_16; + public static final Image RADIO_EMPTY_16; + public static final Image RADIO_FULL_16; + public static final Image RADIO_EMPTY_GRAYED_16; + public static final Image RADIO_FULL_GRAYED_16; + public static final Image CHECK_EMPTY_16; + public static final Image CHECK_FULL_16; + public static final Image TRASH_16; + + static { + USER_16 = new Image("/packages/portalserver/www/assets/User16.gif"); + USER_16.setBorder("0"); + USER_16.lock(); + + GROUP_16 = new Image("/packages/portalserver/www/assets/Group16.gif"); + GROUP_16.setBorder("0"); + GROUP_16.lock(); + + LEFT_16 = new Image("/assets/cw/general/left.gif"); + LEFT_16.setBorder("0"); + LEFT_16.lock(); + + RIGHT_16 = new Image("/assets/cw/general/right.gif"); + RIGHT_16.setBorder("0"); + RIGHT_16.lock(); + + UP_16 = new Image("/assets/cw/general/up.gif"); + UP_16.setBorder("0"); + UP_16.lock(); + + DOWN_16 = new Image("/assets/cw/general/down.gif"); + DOWN_16.setBorder("0"); + DOWN_16.lock(); + + RADIO_EMPTY_16 = + new Image("/packages/portalserver/www/assets/RadioEmpty16.gif"); + RADIO_EMPTY_16.setBorder("0"); + RADIO_EMPTY_16.lock(); + + RADIO_FULL_16 = + new Image("/packages/portalserver/www/assets/RadioFull16.gif"); + RADIO_FULL_16.setBorder("0"); + RADIO_FULL_16.lock(); + + RADIO_EMPTY_GRAYED_16 = + new Image("/packages/portalserver/www/assets/RadioEmptyGrayed16.gif"); + RADIO_EMPTY_GRAYED_16.setBorder("0"); + RADIO_EMPTY_GRAYED_16.lock(); + + RADIO_FULL_GRAYED_16 = + new Image("/packages/portalserver/www/assets/RadioFullGrayed16.gif"); + RADIO_FULL_GRAYED_16.setBorder("0"); + RADIO_FULL_GRAYED_16.lock(); + + CHECK_EMPTY_16 = + new Image("/packages/portalserver/www/assets/CheckEmpty16.gif"); + CHECK_EMPTY_16.setBorder("0"); + CHECK_EMPTY_16.lock(); + + CHECK_FULL_16 = + new Image("/packages/portalserver/www/assets/CheckFull16.gif"); + CHECK_FULL_16.setBorder("0"); + CHECK_FULL_16.lock(); + + TRASH_16 = new Image("/assets/cw/general/delete.gif"); + TRASH_16.setBorder("0"); + TRASH_16.lock(); + + } + +}; diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/Initializer.java b/ccm-portalserver/src/com/arsdigita/portalserver/Initializer.java new file mode 100644 index 000000000..e62068f16 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/Initializer.java @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + +import com.arsdigita.db.*; +// import com.arsdigita.domain.*; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.domain.DomainObject; +// import com.arsdigita.persistence.*; +import com.arsdigita.kernel.ACSObjectInstantiator; +import com.arsdigita.kernel.NoValidURLException; +import com.arsdigita.kernel.URLFinder; +import com.arsdigita.kernel.URLService; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.OID; +import com.arsdigita.persistence.pdl.*; +import com.arsdigita.portal.AgentPortlet; +import com.arsdigita.portalserver.admin.PSAdmin; +// import com.arsdigita.runtime.*; +import com.arsdigita.portalserver.personal.MyPortalsPortlet; +import com.arsdigita.portalserver.personal.PersonalPortal; +import com.arsdigita.portalserver.personal.PersonalPortalConfig; +import com.arsdigita.portalserver.personal.PersonalPortalCreator; +import com.arsdigita.portalserver.ui.admin.PortalCreator; +import com.arsdigita.portalserver.ui.admin.PortalSiteMap; +import com.arsdigita.runtime.CompoundInitializer; +import com.arsdigita.runtime.RuntimeConfig; +import com.arsdigita.runtime.DomainInitEvent; +import com.arsdigita.runtime.LegacyInitializer; +import com.arsdigita.runtime.PDLInitializer; +// import com.arsdigita.web.*; +import com.arsdigita.web.Application; + +/** + * PortalserverInitializer + * + * @author Jim Parsons <jparsons@redhat.com> + * @version $Revision: #19 $ $Date: 2004/08/17 $ + **/ + +public class Initializer extends CompoundInitializer { + + + public Initializer() { + final String url = RuntimeConfig.getConfig().getJDBCURL(); + final int database = DbHelper.getDatabaseFromURL(url); + + add(new PDLInitializer + (new ManifestSource + ("ccm-portalserver.pdl.mf", + new NameFilter(DbHelper.getDatabaseSuffix(database), "pdl")))); + + // add(new LegacyInitializer("com/arsdigita/portalserver/enterprise.init")); + } + + + /** + * + * @param evt + */ + + @Override + public void init(DomainInitEvent evt) { + super.init(evt); + + // Prerequisite to access basic potalsite (at /administration/) + DomainObjectFactory.registerInstantiator( + PortalSite.BASE_DATA_OBJECT_TYPE, new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new PortalSite(dataObject); + } + } + ); + + // XXX Unknown which routine really requires this. + DomainObjectFactory.registerInstantiator( + Role.BASE_DATA_OBJECT_TYPE, new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new Role(dataObject); + } + } + ); + + // Prerequisite to access AddTab in portal administration + DomainObjectFactory.registerInstantiator( + PortalTab.BASE_DATA_OBJECT_TYPE, new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new PortalTab(dataObject); + } + } + ); + + // Prerequisite to access ?? + DomainObjectFactory.registerInstantiator( + SubPortalTab.BASE_DATA_OBJECT_TYPE, new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new SubPortalTab(dataObject); + } + } + ); + + // Prerequisite to access /portal-admin/ page + DomainObjectFactory.registerInstantiator( + PSAdmin.BASE_DATA_OBJECT_TYPE, new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new PSAdmin(dataObject); + } + } + ); + + + // FORMERLY ui.admin.Initializer + + // Prerequisite to access /portal-admin/portal-create/ page + DomainObjectFactory.registerInstantiator( + PortalCreator.BASE_DATA_OBJECT_TYPE, new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new PortalCreator(dataObject); + } + } + ); + + // Prerequisite to access /portal-admin/portal-sitemap page + DomainObjectFactory.registerInstantiator( + PortalSiteMap.BASE_DATA_OBJECT_TYPE, new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new PortalSiteMap(dataObject); + } + } + ); + + + + // Registering internal portlets + + // Prerequisite to access ?? + DomainObjectFactory.registerInstantiator( + AgentPortlet.BASE_DATA_OBJECT_TYPE, new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new AgentPortlet(dataObject); + } + } + ); + + // Prerequisite to access ?? + DomainObjectFactory.registerInstantiator( + ApplicationDirectoryPortlet.BASE_DATA_OBJECT_TYPE, + new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new ApplicationDirectoryPortlet(dataObject); + } + } + ); + + // Prerequisite to access ?? + DomainObjectFactory.registerInstantiator( + MyPortalsPortlet.BASE_DATA_OBJECT_TYPE, + new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new MyPortalsPortlet(dataObject); + } + } + ); + + // Prerequisite to access ?? + DomainObjectFactory.registerInstantiator( + PortalNavigatorPortlet.BASE_DATA_OBJECT_TYPE, + new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new PortalNavigatorPortlet(dataObject); + } + } + ); + + // Prerequisite to access ?? + DomainObjectFactory.registerInstantiator( + PortalSummaryPortlet.BASE_DATA_OBJECT_TYPE, + new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new PortalSummaryPortlet(dataObject); + } + } + ); + + + // FORMERLY personal.Initializer + + // Prerequisite to access /personal-portal/[userId]/ + new PersonalPortalConfig(); + + // Prerequisite to access ?? + DomainObjectFactory.registerInstantiator( + PersonalPortalCreator.BASE_DATA_OBJECT_TYPE, + new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new PersonalPortalCreator(dataObject); + } + } + ); + + // Prerequisite to access ?? + DomainObjectFactory.registerInstantiator( + PersonalPortal.BASE_DATA_OBJECT_TYPE, + new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new PersonalPortal(dataObject); + } + } + ); + + + + // Why URLFinder for forum is needed here?? + URLFinder forumFinder = new URLFinder() { + public String find(OID oid) throws NoValidURLException { + Application app = Application.retrieveApplication(oid); + return app.getPrimaryURL(); + } + public String find(OID oid, String context) throws NoValidURLException { + return find(oid); + } + + }; + URLService.registerFinder(Application.BASE_DATA_OBJECT_TYPE, forumFinder); + + // XXX Unknown which routine really requires this. + CWURLFinder finder = new CWURLFinder("admin"); + // XXX Unknown which routine requires this. + URLService.registerFinder(PortalSite.BASE_DATA_OBJECT_TYPE, finder); + + + } + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/Loader.java b/ccm-portalserver/src/com/arsdigita/portalserver/Loader.java new file mode 100644 index 000000000..ab6f7262d --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/Loader.java @@ -0,0 +1,961 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +package com.arsdigita.portalserver; + + +// import com.arsdigita.db.*; +import com.arsdigita.domain.*; +import com.arsdigita.kernel.ACSObjectInstantiator; +import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.KernelExcursion; +import com.arsdigita.kernel.ResourceSetup; +import com.arsdigita.loader.*; +import com.arsdigita.persistence.DataObject; + +import com.arsdigita.portal.AgentPortlet; +import com.arsdigita.portal.PortletSetup; +import com.arsdigita.portal.PortletType; +import com.arsdigita.portal.apportlet.AppPortletSetup; + +import com.arsdigita.portalserver.admin.PSAdmin; +import com.arsdigita.portalserver.personal.MyPortalsPortlet; +import com.arsdigita.portalserver.personal.PersonalPortal; +import com.arsdigita.portalserver.personal.PersonalPortalCreator; +import com.arsdigita.portalserver.ui.admin.PortalCreator; +import com.arsdigita.portalserver.ui.admin.PortalSiteMap; + +import com.arsdigita.runtime.*; +import com.arsdigita.web.Application; +import com.arsdigita.web.ApplicationSetup; +import com.arsdigita.web.ApplicationType; + +// USED BY loadSubsite() which es meant to replace the applications mounted +// at root url dispatcher by portalserver dispatcher. Not used anymore, the +// page at root address is now determined in a different way. +//import com.arsdigita.kernel.PackageType; +//import com.arsdigita.kernel.PackageInstance; +//import com.arsdigita.kernel.SiteNode; + +import org.apache.log4j.Logger; + +/** + * Portal Server Loader + * + * @author Jim Parsons <jparsons@redhat.com> + * @version $Revision: #2 $ $Date: 2004/08/17 $ + **/ + +public class Loader extends PackageLoader { + + + /** Logger instance for debugging */ + private static final Logger s_log = Logger.getLogger(Loader.class); + + /** + * Run script invoked by com.arsdigita.packing loader script. + * + * @param ctx + */ + public void run(final ScriptContext ctx) { + + new KernelExcursion() { + public void excurse() { + setEffectiveParty(Kernel.getSystemParty()); + + loadPortalSiteApplicationType(); + buildDefaultThemes(); + setupAdminPortal(); + loadPortalTabApplicationType(); //formerly ResourceType rtype = setupResource(); + loadSubPortalTabApplicationType(); // formerly ResourceType restype = setupSubPortal(); + + loadPortalSiteAdminApplicationType(); + setupPortalSiteAdminInstance(); + + // formerly from ui.admin.Initializer + loadPortalCreatorApplicationType(); + loadPortalSitemapApplicationType(); + setupPortalCreatorInstance(); + setupPortalSitemapInstance(); + + // formerly from personal.Initializer + loadPersonalPortalCreatorApplicationType(); + setupPersonalPortalCreatorInstance(); + + loadPersonalPortalApplicationType(); + setupMyPortalsPortlet(); + + // Loading internal portlets + setupAgentPortlet(); + setupApplicationDirectoryPortlet(); + setupPortalNavigatorPortlet(); + setupPortalSummaryPortlet(); + + // loadSubsite(); + } + }.run(); + + s_log.warn("Done"); + } + + + // //////////////////////////////////////////////////////////////////////// + // + // S e t u p o f a p p l i c a t i o n t y p e s + // + // //////////////////////////////////////////////////////////////////////// + + + /** + * Creates a PortalSite, one of the domain classes of the portalserver + * package, ApplicationType as a legacy-free type of application type. + * + * NOTE: The wording in the title parameter of ApplicationType determines + * the name of the subdirectory for the XSL stylesheets. + * It gets "urlized", i.e. trimming leading and trailing blanks and replacing + * blanks between words and illegal characters with an hyphen and converted + * to lower case. + * Example: "Portal Server" will become "portal-server". + * + * Creates an entry in table application_types and a corresponding entry in + * apm_package_types + */ + private void loadPortalSiteApplicationType() { + + // Step 1: Create an application type for portalserver + // Try: new style legacy free application + // ApplicationType type = + // new ApplicationType("Portal Site", // creates portalsite as + // // module name for XSL + // PortalSite.BASE_DATA_OBJECT_TYPE ); + // type.setDescription + // ("A Portal Site is a center for content aggregation. It usually" + + // "has its own set of applications, such as a discussion forum" + + // "and content items, as well as a list of participants."); + +/* s_log.info("PackageType 'portalsite' is not installed. " + + "Installing now..."); + + // Stylesheet stylesheet = Stylesheet.createStylesheet + // ("/packages/portalserver/xsl/portalserver.xsl"); + + PackageType packageType = PackageType.create + ("portalsite", "PortalSite", "PortalSites", + "http://arsdigita.com/portalsite"); + // packageType.addStylesheet(stylesheet); + packageType.setDispatcherClass + ("com.arsdigita.portalserver.ui.PortalDispatcher"); + packageType.save(); +*/ + //Step 2: Create themes + // buildDefaultThemes(); + + // Step 3: Create legacy compatible ApplicationType + ApplicationType type = ApplicationType.createApplicationType( + "portalsite", + "Portal Site", + PortalSite.BASE_DATA_OBJECT_TYPE); + type.setDescription + ("A Portal Site is a center for content aggregation. It usually" + + "has its own set of applications, such as a discussion forum " + + "and content items, as well as a list of participants."); + // Current code requires an apps specific dispatcher class. Has to be + // modified to be able to create a legacy free app type. + type.setDispatcherClass + ("com.arsdigita.portalserver.ui.PortalDispatcher"); + +/* + ApplicationSetup setup = new ApplicationSetup(s_log); + + setup.setApplicationObjectType(PortalSite.BASE_DATA_OBJECT_TYPE); + // setup.setPackageType(packageType); + setup.setKey("portalsite"); + setup.setTitle("Portal Site"); + setup.setDescription + ("A Portal Site is a center for content aggregation. It usually" + + "has its own set of applications, such as a discussion forum" + + "and content items, as well as a list of participants."); + setup.setDispatcherClass + ("com.arsdigita.portalserver.ui.PortalDispatcher"); + setup.setPortalApplication(false); + setup.setInstantiator(new ACSObjectInstantiator() { + @Override + protected DomainObject doNewInstance(DataObject dataObject) { + return new PortalSite(dataObject); + } + }); + setup.run(); +*/ + /* Should not be requiered here + DomainObjectFactory.registerInstantiator( + Role.BASE_DATA_OBJECT_TYPE, new ACSObjectInstantiator() { + public DomainObject doNewInstance(DataObject dataObject) { + return new Role(dataObject); + } + } + ); + * + */ + + } + + /** + * + * @return + */ + private void loadPortalTabApplicationType() { + // formerly private void setupResource() in OldInitializer { + // legt an in application_types object_type: c.ad.workspace.WorkspaceTab + // nichts in applications, + // nichts in apm_package_types, ps_*, acs_objects + + ResourceSetup setup = new ResourceSetup(s_log); + + setup.setTitle("PortalTab"); + setup.setResourceObjectType(PortalTab.BASE_DATA_OBJECT_TYPE); + setup.setDescription("A Portal Tab!"); + + setup.setInstantiator(new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new PortalTab(dataObject); + } + }); + setup.run(); + + } + + + /** + * + * @return + */ + private void loadSubPortalTabApplicationType() { + // formerly private void setupSubPortalTab() { in OldInitializer + // legt an in application_types object_type: c.ad.workspace.SubWorkspaceTab + // ohne Eintrag in package_type_id + // nichts in applications, + // nichts in apm_package_types, ps_*, acs_objects + + ResourceSetup setup = new ResourceSetup(s_log); + + setup.setTitle("SubPortalTab"); + setup.setResourceObjectType(SubPortalTab.BASE_DATA_OBJECT_TYPE); + setup.setDescription("A SubPortal Tab!"); + + setup.setInstantiator(new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new SubPortalTab(dataObject); + } + }); + setup.run(); + + } + + /* FORMERLY admin.Initializer */ + + /** + * + */ + // replaced formerly startup() meothod in admin.Initializer + private void loadPortalSiteAdminApplicationType() { + + // erstellt Eintrag in apm_package_types (key portal-admin mit eigenem + // dispatcher_class, nciht .... JSPApplicationDispatcher), Eintrag in + // apm_packages, in application_tyxpes mit object_type = c.ad.admin.CWAdmin + // (statt Klassenname PSAdmin, liegt an Eintrag für BASE_DATA_OBJECT_TYPE), + // in applications mit primary_url=/portal-admin/ + // in acs_object mit default_domain_class=c.ad.ps.admin.PSAdmin und + // object_type=c.ad.admin.CWAdmin, ebenfalls wg. BASE_DATA_OBJ_TYPE + + ApplicationType type = ApplicationType.createApplicationType( + "portal-admin", + "Portal Server Site Administration", + PSAdmin.BASE_DATA_OBJECT_TYPE); + type.setDescription ("Displays common administration tasks."); + // Current code requires an apps specific dispatcher class. Has to be + // modified to be able to create a legacy free app type. + type.setDispatcherClass + ("com.arsdigita.portalserver.admin.ui.Dispatcher"); +/* + ApplicationSetup setup = new ApplicationSetup(s_log); + + setup.setApplicationObjectType(PSAdmin.BASE_DATA_OBJECT_TYPE); + setup.setTitle("Portal Server Site Administration"); + setup.setDescription("Displays common administration tasks."); + setup.setPortalApplication(false); + setup.setKey("portal-admin"); + // db based stylesheets no longer used. + // setup.setStylesheet("/packages/portalserver/xsl/portalserver.xsl"); + setup.setDispatcherClass("com.arsdigita.portalserver.admin.ui.Dispatcher"); + setup.setInstantiator(new ACSObjectInstantiator() { + @Override + protected DomainObject doNewInstance(DataObject dataObject) { + return new PSAdmin(dataObject); + } + }); + // setupAdminInstance(setup.run()); + setup.run(); + // setupPortalSiteAdminInstance(setup.run()) + */ + } + + + // FORMERLY ui.admin.Initializer + /** + * Creates a PortalCreator, another of the domain classes of the portalserver + * package, ApplicationType as a legacy-comp type of application type. + * + */ + private void loadPortalCreatorApplicationType() { + // formerly private ApplicationType setupPortalCreator() { in ui.admin.Initializer + + ApplicationType type = ApplicationType.createApplicationType( + "portal-create", + "Portal Creator", + PortalCreator.BASE_DATA_OBJECT_TYPE); + type.setDescription ("Creates portals."); + // Current code requires an apps specific dispatcher class. Has to be + // modified to be able to create a legacy free app type. + type.setDispatcherClass + ("com.arsdigita.portalserver.ui.admin.PortalCreateDispatcher"); +/* + ApplicationSetup setup = new ApplicationSetup(s_log); + setup.setApplicationObjectType(PortalCreator.BASE_DATA_OBJECT_TYPE); + setup.setTitle("Portal Creator"); + setup.setDescription("Creates portals."); + setup.setWorkspaceApplication(false); + setup.setKey("portal-create"); +// setup.setStylesheet("/packages/portalserver/xsl/portalserver.xsl"); + setup.setDispatcherClass( + "com.arsdigita.portalserver.ui.admin.PortalCreateDispatcher"); + setup.setInstantiator(new ACSObjectInstantiator() { + @Override + protected DomainObject doNewInstance(DataObject dataObject) { + return new PortalCreator(dataObject); + } + }); + + setup.run(); + // return setup.run(); +*/ + } + + + /** + * + * @return + */ + private void loadPortalSitemapApplicationType() { + // formerly private ApplicationType setupPortalSitemapper() { + + ApplicationType type = ApplicationType.createApplicationType( + "portal-sitemap", + "Portal Site Map", + PortalSiteMap.BASE_DATA_OBJECT_TYPE); + type.setDescription ("Displays and manages Portals."); + // Current code requires an apps specific dispatcher class. Has to be + // modified to be able to create a legacy free app type. + type.setDispatcherClass + ("com.arsdigita.portalserver.ui.admin.PortalSiteMapDispatcher"); + +/* ApplicationSetup setup = new ApplicationSetup(s_log); + setup.setApplicationObjectType(PortalSiteMap.BASE_DATA_OBJECT_TYPE); + setup.setTitle("Portal Site Map"); + setup.setDescription("Displays and manages Portals"); + setup.setWorkspaceApplication(false); + setup.setKey("portal-sitemap"); +// setup.setStylesheet("/packages/portalserver/xsl/portal-sitemap.xsl"); + setup.setDispatcherClass( + "com.arsdigita.portalserver.ui.admin.PortalSiteMapDispatcher"); + setup.setInstantiator(new ACSObjectInstantiator() { + @Override + protected DomainObject doNewInstance(DataObject dataObject) { + return new PortalSiteMap(dataObject); + } + }); + + setup.run(); */ + // return setup.run(); + } + + + /* FORMERLY personal.Initializer */ + + + /** + * + * @return + */ + private void loadPersonalPortalCreatorApplicationType() { + // private ApplicationType loadPersonalPortalCreatorApplicationType() { + // formerly private ApplicationType setupPersonalPortalCreatorApplication() { + + ApplicationType type = ApplicationType.createApplicationType( + "personal-portal-creator", + "Personal Portal Creator", + PersonalPortalCreator.BASE_DATA_OBJECT_TYPE); + type.setDescription ("Responsible for creating personal portals."); + // Current code requires an apps specific dispatcher class. Has to be + // modified to be able to create a legacy free app type. + type.setDispatcherClass + ("com.arsdigita.portalserver.personal.PersonalPortalCreatorDispatcher"); + + // return type; + +/* ApplicationSetup setup = new ApplicationSetup(s_log); + + setup.setApplicationObjectType + (PersonalPortalCreator.BASE_DATA_OBJECT_TYPE); + setup.setKey("personal-portal-creator"); + setup.setTitle("Personal Portal Creator"); + setup.setDescription("Responsible for creating personal portals."); + // db based stylesheets nolonger used + // setup.setStylesheet("/packages/portalserver/xsl/portalserver.xsl"); + setup.setDispatcherClass + ("com.arsdigita.portalserver.personal.PersonalPortalCreatorDispatcher"); + setup.setPortalApplication(false); + setup.setInstantiator(new ACSObjectInstantiator() { + @Override + protected DomainObject doNewInstance(DataObject dataObject) { + return new PersonalPortalCreator(dataObject); + } + }); + + return setup.run(); */ + } + + + private void loadPersonalPortalApplicationType() { + // private ApplicationType loadPersonalPortalApplicationType() { + // formerly private ApplicationType setupPersonalPortalApplication() { + + ApplicationType type = ApplicationType.createApplicationType( + "personal-portal", + "Personal Portal", + PersonalPortal.BASE_DATA_OBJECT_TYPE); + type.setDescription ("A portal for an individual."); + // Current code requires an apps specific dispatcher class. Has to be + // modified to be able to create a legacy free app type. + type.setDispatcherClass + ("com.arsdigita.portalserver.personal.PersonalPortalDispatcher"); + + +/* ApplicationSetup setup = new ApplicationSetup(s_log); + + setup.setApplicationObjectType(PersonalPortal.BASE_DATA_OBJECT_TYPE); + setup.setKey("personal-portal"); + setup.setTitle("Personal Portal"); + setup.setDescription("A portal for an individual."); + // setup.setStylesheet("/packages/portalserver/xsl/portalserver.xsl"); + setup.setDispatcherClass + ("com.arsdigita.portalserver.personal.PersonalPortalDispatcher"); + setup.setPortalApplication(false); + setup.setInstantiator(new ACSObjectInstantiator() { + @Override + protected DomainObject doNewInstance(DataObject dataObject) { + return new PersonalPortal(dataObject); + } + }); + + ApplicationType type = setup.run(); + + // XXX This must go after setup.run(). Need more elegant approach. + // pboy: uses ResourceType.registerResourceTypeConfig() which registers + // in a hash map. Therefore: not suitable for a loader, may have to be + // moved into initializer! + // new PersonalPortalConfig(); + + return type; */ + } + + + // //////////////////////////////////////////////////////////////////////// + // + // S e t u p o f P O R T A L a p p l i c a t i o n s + // + // //////////////////////////////////////////////////////////////////////// + private void setupAdminPortal() { + + // First check, whether an instance of /administration / is already + // installed. + // Running in a Loader, this is just impossible. So we can create + // /administration/ immediately + // try { + // SiteNode sn = SiteNode.getSiteNode("/administration", false); + // if (!"administration".equals(sn.getName())) { + PortalSite ps = PortalSite.createPortalSite( + "administration", "Administration", null); + ps.setMission("Administration Portal"); + ps.save(); + // } + // } catch (DataObjectNotFoundException e) { + // Assert.fail(e.getMessage()); + // } + } + + /* FORMERLY admin.Initializer */ + + /** + * Setup an PortalServer Administration Instance as legacy compatible + * application. + * + * @param type + */ + // private void setupPortalSiteAdminInstance(final ApplicationType type) { + private void setupPortalSiteAdminInstance() { + + if (!Application.isInstalled(PSAdmin.BASE_DATA_OBJECT_TYPE, + "/portal-admin/")) { + s_log.info("There is no Portal Admin application instance on " + + "/portal-admin/. Installing now."); + + // KernelExcursion ex = new KernelExcursion() { + // protected void excurse() { + // setParty(Kernel.getSystemParty()); + Application app = Application.createApplication + (PSAdmin.BASE_DATA_OBJECT_TYPE, + "portal-admin", "Site Administration", null); + + app.save(); + // } + // }; + // ex.run(); + + s_log.info("Done installing Portal Admin on /portal-admin/."); + } + } + + + /* FORMERLY ui.admin.Initializer */ + + private void setupPortalCreatorInstance() { + // formerly private void setupPortalCreate(ApplicationType type) { + + if (!Application.isInstalled(PortalCreator.BASE_DATA_OBJECT_TYPE, + "/portal-admin/portal-create/")) { + Application admin = + Application.retrieveApplicationForPath("/portal-admin/"); + + if (admin == null) { + s_log.warn("There is no application at /portal-admin/ so I " + + "can't install the portal create application."); + return; + } + + s_log.info("There is no Portal Creator application instance " + + "on /user-profile/. Installing now."); + + Application app = Application.createApplication + (PortalCreator.BASE_DATA_OBJECT_TYPE, + "portal-create", "Create Top-Level Portals", admin); + app.setDescription("Create top-level portals."); + + app.save(); + + s_log.info("Done installing Portal Creator on " + + "/portal-admin/portal-create/."); + } + + } + + private void setupPortalSitemapInstance() { + // private void setupPortalSitemapInstance(ApplicationType type) { + + if (!Application.isInstalled(PortalSiteMap.BASE_DATA_OBJECT_TYPE, + "/portal-admin/portal-sitemap/")) { + Application admin = + Application.retrieveApplicationForPath("/portal-admin/"); + + if (admin == null) { + s_log.warn("There is no application at /portal-admin/ so I " + + "can't install the portal sitemap application."); + return; + } + + s_log.warn("There is no Portal Site Map application instance " + + "on /portal-admin/. Installing now."); + + Application app = Application.createApplication + // (type, "portal-sitemap", "Portal Site Map", admin); + (PortalSiteMap.BASE_DATA_OBJECT_TYPE, + "portal-sitemap", "Portal Site Map", admin); + app.setDescription("Portal Site Map"); + + app.save(); + + s_log.warn("Done installing Portal Site Map on " + + "/portal-admin/portal-sitemap/."); + } + } + + + + /* FORMERLY personal.Initializer */ + + + private void setupPersonalPortalCreatorInstance() { + + // Create an instance of the personal portal creator at + // /personal-portal/. + + boolean creatorInstalled = Application.isInstalled + (PersonalPortalCreator.BASE_DATA_OBJECT_TYPE, + "/personal-portal/"); + + if (!creatorInstalled) { + + // No KernelExcursion needed here because Loader already has it. + // KernelExcursion ex = new KernelExcursion() { + // protected void excurse() { + // setParty(Kernel.getSystemParty()); + // creates either a legacy free application or a legacy compatible, + // depending of its application type. + Application creatorApp = Application.createApplication + (PersonalPortalCreator.BASE_DATA_OBJECT_TYPE, + "personal-portal", "Personal Portal Creator", null); + creatorApp.save(); + // } + // }; + // ex.run(); + + + } + } + + + + + // //////////////////////////////////////////////////////////////////////// + // + // S e t u p o f i n t e r n a l p o r t l e t s + // + // //////////////////////////////////////////////////////////////////////// + + /** + * Creates a PortletType (persistent object) for AgentPortlet. + * Instances (Portlets) are created by user interface or programmatically + * by configuration. + */ + private void setupAgentPortlet() { + PortletSetup setup = new PortletSetup(s_log); + + setup.setPortletObjectType + (AgentPortlet.BASE_DATA_OBJECT_TYPE); + setup.setTitle("Agent"); + setup.setDescription + ("Acts as agent or proxy for another portlet."); + setup.setProfile(PortletType.WIDE_PROFILE); + setup.setInstantiator(new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new AgentPortlet(dataObject); + } + }); + + setup.run(); + } + + /** + * Creates a PortletType (persistent object) for ApplicationDirectoryPortlet. + * Instances (Portlets) are created by user interface or programmatically + * by configuration. + */ + private void setupApplicationDirectoryPortlet() { + AppPortletSetup setup = + new AppPortletSetup(s_log); + + setup.setPortletObjectType + (ApplicationDirectoryPortlet.BASE_DATA_OBJECT_TYPE); + setup.setTitle("Application Directory"); + setup.setDescription("Provides links to the workspace's applications."); + setup.setProfile(PortletType.NARROW_PROFILE); + setup.setPortalApplication(true); + setup.setInstantiator(new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new ApplicationDirectoryPortlet(dataObject); + } + }); + + setup.run(); + } + + /** + * + */ + private void setupMyPortalsPortlet() { + AppPortletSetup setup = new AppPortletSetup(s_log); + + setup.setPortletObjectType + (MyPortalsPortlet.BASE_DATA_OBJECT_TYPE); + setup.setTitle("My Portals"); + setup.setDescription + ("Displays links to portals to which you belong."); + setup.setProfile(PortletType.NARROW_PROFILE); + setup.setPortalApplication(true); + setup.setInstantiator(new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new MyPortalsPortlet(dataObject); + } + }); + + setup.run(); + } + + + /** + * Creates a PortletType (persistent object) for PortalNavigatorPortlet. + * Instances (Portlets) are created by user interface or programmatically + * by configuration. + */ + private void setupPortalNavigatorPortlet() { + + // Create a PortletType for PortalNavigatorPortlet + AppPortletSetup setup = + new AppPortletSetup(s_log); + + setup.setPortletObjectType + (PortalNavigatorPortlet.BASE_DATA_OBJECT_TYPE); + setup.setTitle("Portal Navigator"); + setup.setDescription + ("Provides links to portal associated with the current " + + "portal."); + setup.setProfile(PortletType.NARROW_PROFILE); + setup.setPortalApplication(true); + setup.setInstantiator(new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new PortalNavigatorPortlet(dataObject); + } + }); + + setup.run(); + } + + /** + * Creates a PortletType (persistent object) for PortalSummaryPortlet. + * Instances (Portlets) are created by user interface or programmatically + * by configuration. + */ + private void setupPortalSummaryPortlet() { + AppPortletSetup setup = new AppPortletSetup(s_log); + + setup.setPortletObjectType + (PortalSummaryPortlet.BASE_DATA_OBJECT_TYPE); + setup.setTitle("Portal Summary"); + setup.setProfile(PortletType.NARROW_PROFILE); + setup.setPortalApplication(true); + setup.setInstantiator(new ACSObjectInstantiator() { + @Override + public DomainObject doNewInstance(DataObject dataObject) { + return new PortalSummaryPortlet(dataObject); + } + }); + + setup.run(); + } + + + + // //////////////////////////////////////////////////////////////////////// + // + // + // //////////////////////////////////////////////////////////////////////// + + /** + * Determines the ApplicationType mounted at the root node (as a package type) + * and replaces its dispatcher class with its own. + * This dispatcher class sets the class which is used for login. The class is + * persisted into database. + * + * Root URL request will be redirected to the users portal page (or login) + * + * @ deprecated the method used by the dispatcher in its current version is + * no longer available. Currently without direct replacement. The current + * version of core now uses a different method to determine the page at + * root address. So this method is of no use anymore! + * Whether it is used or not makes no difference. + */ +// USED BY loadSubsite() which es meant to replace the applications mounted +// at root url dispatcher by portalserver dispatcher. Not used anymore, the +// page at root address is now determined in a different way. +/* + private void loadSubsite() { + // String stylesheetName = ""; + String sDispatcher = ""; + + SiteNode rootNode = SiteNode.getRootSiteNode(); + + PackageInstance packageInstance = rootNode.getPackageInstance(); + if (packageInstance == null) { + throw new IllegalStateException + ("No package instance mounted at the root node"); + } + PackageType subsite = packageInstance.getType(); + + // getType() returns a disconnected object. To get a connected object + // we do a findByKey(key). + String packageKey = subsite.getKey(); + try { + subsite = PackageType.findByKey(packageKey); + } catch (DataObjectNotFoundException e) { + throw new IllegalStateException + ("Package Type with key \"" + packageKey + "\" was not found.\n"); + } + + // Create default stylesheet. + // stylesheetName = "/packages/login/xsl/login_ps_en.xsl"; + + // s_log.warn("Adding stylesheet: " + stylesheetName); + // subsite.addStylesheet(Stylesheet.createStylesheet(stylesheetName)); + + // Set subsite dispatcher class. + subsite.setDispatcherClass( + "com.arsdigita.portalserver.pslogin.PSSubsiteDispatcher"); + } +*/ + + /** + * PortalSite may have its own styling elements (portal themes). Loads some + * default styles which are available in a drop down menue for a user. + */ + private void buildDefaultThemes() { + + Theme theme0 = new Theme("Red Hat"); + theme0.setDescription("A cool corporate theme"); + theme0.setContextBarColor("#E1E1E1"); + theme0.setContextBarTextColor("#3F3F3F"); + theme0.setActiveTabColor("#a21e1e"); + theme0.setInactiveTabColor("#dddddd"); + theme0.setInactiveTabTextColor("#555555"); + theme0.setActiveTabTextColor("#ffffff"); + theme0.setTopRuleColor("#a21e1e"); + theme0.setBottomRuleColor("#a21e1e"); + theme0.setPortletHeaderColor("#a21e1e"); + theme0.setPortletIconColor("#a21e1e"); + theme0.setPortletHeaderTextColor("#ffffff"); + theme0.setPageBGColor("#ffffff"); + theme0.setBodyTextColor("#000000"); + theme0.setNarrowBGColor("#dddddd"); + theme0.save(); +/* + Theme theme1 = new Theme("Celtic Fever"); + theme1.setDescription("A theme for Celtic NBA fans"); + theme1.setContextBarColor("#008800"); + theme1.setActiveTabColor("#008800"); + theme1.setInactiveTabColor("#002200"); + theme1.setInactiveTabTextColor("#ffffff"); + theme1.setActiveTabTextColor("#ffffff"); + theme1.setTopRuleColor("#008800"); + theme1.setBottomRuleColor("#008800"); + theme1.setPortletHeaderColor("#006600"); + theme1.setPortletIconColor("#006600"); + theme1.setPortletHeaderTextColor("#000000"); + theme1.setPageBGColor("#ffffff"); + theme1.setPageBGImage("/assets/cw/workspace/bg_bos.gif"); + theme1.setBodyTextColor("#000000"); + theme1.setNarrowBGColor("#ddeedd"); + theme1.save(); +*/ + Theme theme2 = new Theme("Bright Day"); + theme2.setDescription("A sunny, cloudless sky"); + theme2.setContextBarColor("#003366"); + theme2.setContextBarTextColor("#FFFFFF"); + theme2.setActiveTabColor("#93bee2"); + theme2.setInactiveTabColor("#d8e8f5"); + theme2.setInactiveTabTextColor("#000000"); + theme2.setActiveTabTextColor("#000000"); + theme2.setTopRuleColor("#93bee2"); + theme2.setBottomRuleColor("#93bee2"); + theme2.setPortletHeaderColor("#cccccc"); + theme2.setPortletIconColor("#cccccc"); + theme2.setPortletHeaderTextColor("#000000"); + theme2.setPageBGColor("#ffffff"); + theme2.setPageBGImage(""); + theme2.setNarrowBGColor("#dddddd"); + theme2.setBodyTextColor("#000000"); + + theme2.save(); + + Theme theme3 = new Theme("Harvest"); + theme3.setDescription("High Heat"); + theme3.setContextBarColor("#ff9966"); + theme3.setContextBarTextColor("#ffffff"); + theme3.setActiveTabColor("#ff9966"); + theme3.setInactiveTabColor("#ffcc99"); + theme3.setInactiveTabTextColor("#000000"); + theme3.setActiveTabTextColor("#000000"); + theme3.setTopRuleColor("#ff9966"); + theme3.setBottomRuleColor("#ff9966"); + theme3.setPortletHeaderColor("#ff9966"); + theme3.setPortletIconColor("#ff9966"); + theme3.setPortletHeaderTextColor("#000000"); + theme3.setPageBGColor("#ffffff"); + theme3.setPageBGImage(""); + theme3.setNarrowBGColor("#ffffcc"); + theme3.setBodyTextColor("#000000"); + + theme3.save(); + + Theme theme4 = new Theme("Desert"); + theme4.setDescription("High Heat"); + theme4.setContextBarColor("#cccc99"); + theme4.setContextBarTextColor("#FFFFFF"); + theme4.setActiveTabColor("#cccc99"); + theme4.setInactiveTabColor("#ededca"); + theme4.setInactiveTabTextColor("#000000"); + theme4.setActiveTabTextColor("#000000"); + theme4.setTopRuleColor("#cccc99"); + theme4.setBottomRuleColor("#cccc99"); + theme4.setPortletHeaderColor("#cccc99"); + theme4.setPortletIconColor("#cccc99"); + theme4.setPortletHeaderTextColor("#000000"); + theme4.setPageBGColor("#ffffff"); + theme4.setPageBGImage(""); + theme4.setNarrowBGColor("#ffffcc"); + theme4.setBodyTextColor("#000000"); + + theme4.save(); + + Theme theme5 = new Theme("Stars and Bars"); + theme5.setDescription("Patriotic"); + theme5.setContextBarColor("#cc0000"); + theme5.setContextBarTextColor("#FFFFFF"); + theme5.setActiveTabColor("#cc0000"); + theme5.setInactiveTabColor("#ffffff"); + theme5.setInactiveTabTextColor("#000000"); + theme5.setActiveTabTextColor("#ffffff"); + theme5.setTopRuleColor("#cc0000"); + theme5.setBottomRuleColor("#cc0000"); + theme5.setPortletHeaderColor("#cc0000"); + theme5.setPortletIconColor("#cc0000"); + theme5.setPortletHeaderTextColor("#ffffff"); + theme5.setPageBGColor("#ffffff"); + theme5.setPageBGImage("/assets/cw/backgrounds/stars.gif"); + theme5.setNarrowBGColor("#eeeeee"); + theme5.setBodyTextColor("#000000"); + + theme5.save(); + + } + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/LoggedInLinkWrapper.java b/ccm-portalserver/src/com/arsdigita/portalserver/LoggedInLinkWrapper.java new file mode 100644 index 000000000..dd63e867b --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/LoggedInLinkWrapper.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.kernel.Kernel; + +/** + * Wraps a Link so that it becomes invisible if + * there is no user logged in. + */ +public class LoggedInLinkWrapper extends Link { + + public LoggedInLinkWrapper(PrintListener l) { + super(l); + } + + public boolean isVisible(PageState state) { + if ( Kernel.getContext().getParty() == null ) { + return false; + } else { + return true; + } + } + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/OldInitializer.java.nolongerInUse b/ccm-portalserver/src/com/arsdigita/portalserver/OldInitializer.java.nolongerInUse new file mode 100644 index 000000000..e37c4a4aa --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/OldInitializer.java.nolongerInUse @@ -0,0 +1,420 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.TransactionContext; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.persistence.OID; +import com.arsdigita.web.*; +import com.arsdigita.kernel.*; +// import com.arsdigita.sitenode.*; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.domain.DomainObject; +import com.arsdigita.initializer.Configuration; +import com.arsdigita.initializer.InitializationException; +import com.arsdigita.domain.DataObjectNotFoundException; +import com.arsdigita.portal.PortletType; +import com.arsdigita.portal.AgentPortlet; +import com.arsdigita.portal.apportlet.AppPortletSetup; +import com.arsdigita.portal.PortletSetup; +import com.arsdigita.util.Assert; +import org.apache.log4j.Logger; + +/** + *

    Experimental

    + * + * @author Justin Ross + * @version $Id: OldInitializer.java#4 pboy $ + */ +public class OldInitializer extends BaseInitializer { + + /** Logger instance for Debugging purpose. */ + private static final Logger s_log = Logger.getLogger(Initializer.class); + + private Configuration m_conf = new Configuration(); + + public OldInitializer() throws InitializationException { + super(); + + m_conf.initParameter("urlPathPrefix", "XXX", String.class); + } + + public Configuration getConfiguration() { + return m_conf; + } + + public final void doStartup() { + s_log.info("Initializing Portal..."); + + TransactionContext txn = + SessionManager.getSession().getTransactionContext(); + + txn.beginTxn(); + + PackageType portalPackageType = setupPortalPackageType(); + + // ApplicationType portalAppType = setupPortalApplication(); + ApplicationType portalAppType = + setupPortalApplication(portalPackageType); + + setupPortalNavigatorPortlet(); + + setupApplicationDirectoryPortlet(); + + setupPortalSummaryPortlet(); + + setupAgentPortlet(); + + setupAdminPortal(); + + ResourceType rtype = setupResource(); + + ResourceType restype = setupSubPortal(); + + + txn.commitTxn(); + + URLFinder forumFinder = new URLFinder() { + public String find(OID oid) throws NoValidURLException { + Application app = Application.retrieveApplication(oid); + return app.getPrimaryURL(); + } + public String find(OID oid, String context) throws NoValidURLException { + return find(oid); + } + + }; + + URLService.registerFinder(Application.BASE_DATA_OBJECT_TYPE, forumFinder); + + CWURLFinder finder = new CWURLFinder("admin"); + URLService.registerFinder(PortalSite.BASE_DATA_OBJECT_TYPE, finder); + s_log.info("Done initializing PortalSite."); + + + } + + private PackageType setupPortalPackageType() { + try { + return PackageType.findByKey("portalsite"); + } catch (DataObjectNotFoundException nfe) { + s_log.info("PackageType 'portalsite' is not installed. " + + "Installing now..."); + + Stylesheet stylesheet = Stylesheet.createStylesheet + ("/packages/portalserver/xsl/portalserver.xsl"); + + PackageType packageType = PackageType.create + ("portalsite", "PortalSite", "PortalSites", + "http://arsdigita.com/portalsite"); + packageType.addStylesheet(stylesheet); + packageType.setDispatcherClass + ("com.arsdigita.portalserver.ui.PortalDispatcher"); + packageType.save(); + + buildDefaultThemes(); + + return packageType; + } + } + + private ApplicationType setupPortalApplication(PackageType packageType) { + // private ApplicationType setupPortalApplication() { + // Creates a new ApplicationType + // Creates a new ApplicationType + ApplicationSetup setup = new ApplicationSetup(s_log); + + setup.setApplicationObjectType(PortalSite.BASE_DATA_OBJECT_TYPE); + setup.setPackageType(packageType); + // setup.setKey("portalsite"); + setup.setTitle("Portal"); + setup.setDescription + ("A Portal Site is a center for content aggregation. It usually" + + "has its own set of applications, such as a discussion forum" + + "and content items, as well as a list of participants."); + // setup.setDispatcherClass + // ("com.arsdigita.portalserver.ui.PortalDispatcher"); + setup.setPortalApplication(false); + setup.setInstantiator(new ACSObjectInstantiator() { + protected DomainObject doNewInstance(DataObject dataObject) { + return new PortalSite(dataObject); + } + }); + + DomainObjectFactory.registerInstantiator( + Role.BASE_DATA_OBJECT_TYPE, new ACSObjectInstantiator() { + public DomainObject doNewInstance(DataObject dataObject) { + return new Role(dataObject); + } + } + ); + + return setup.run(); + } + + private void setupPortalNavigatorPortlet() { + AppPortletSetup setup = + new AppPortletSetup(s_log); + + setup.setPortletObjectType + (PortalNavigatorPortlet.BASE_DATA_OBJECT_TYPE); + setup.setTitle("Portal Navigator"); + setup.setDescription + ("Provides links to portal associated with the current " + + "portal."); + setup.setProfile(PortletType.NARROW_PROFILE); + setup.setPortalApplication(true); + setup.setInstantiator(new ACSObjectInstantiator() { + public DomainObject doNewInstance(DataObject dataObject) { + return new PortalNavigatorPortlet(dataObject); + } + }); + + setup.run(); + } + + private void setupApplicationDirectoryPortlet() { + AppPortletSetup setup = + new AppPortletSetup(s_log); + + setup.setPortletObjectType + (ApplicationDirectoryPortlet.BASE_DATA_OBJECT_TYPE); + setup.setTitle("Application Directory"); + setup.setDescription("Provides links to the workspace's applications."); + setup.setProfile(PortletType.NARROW_PROFILE); + setup.setPortalApplication(true); + setup.setInstantiator(new ACSObjectInstantiator() { + public DomainObject doNewInstance(DataObject dataObject) { + return new ApplicationDirectoryPortlet(dataObject); + } + }); + + setup.run(); + } + + private void setupPortalSummaryPortlet() { + AppPortletSetup setup = new AppPortletSetup(s_log); + + setup.setPortletObjectType + (PortalSummaryPortlet.BASE_DATA_OBJECT_TYPE); + setup.setTitle("Portal Summary"); + setup.setProfile(PortletType.NARROW_PROFILE); + setup.setPortalApplication(true); + setup.setInstantiator(new ACSObjectInstantiator() { + public DomainObject doNewInstance(DataObject dataObject) { + return new PortalSummaryPortlet(dataObject); + } + }); + + setup.run(); + } + + private void setupAgentPortlet() { + PortletSetup setup = new PortletSetup(s_log); + + setup.setPortletObjectType + (AgentPortlet.BASE_DATA_OBJECT_TYPE); + setup.setTitle("Agent"); + setup.setDescription + ("Acts as agent or proxy for another portlet."); + setup.setProfile(PortletType.WIDE_PROFILE); + setup.setInstantiator(new ACSObjectInstantiator() { + public DomainObject doNewInstance(DataObject dataObject) { + return new AgentPortlet(dataObject); + } + }); + + setup.run(); + } + + private void setupAdminPortal() { + try { + SiteNode sn = SiteNode.getSiteNode("/administration", false); + if (!"administration".equals(sn.getName())) { + PortalSite ps = PortalSite.createPortalSite( + "administration", "Administration", null); + ps.setMission("Administration Portal"); + ps.save(); + } + } catch (DataObjectNotFoundException e) { + Assert.fail(e.getMessage()); + } + } + + private ResourceType setupResource() { + + ResourceSetup setup = new ResourceSetup(s_log); + + setup.setTitle("PortalTab"); + + setup.setResourceObjectType(PortalTab.BASE_DATA_OBJECT_TYPE); + + setup.setDescription("A Portal Tab!"); + + setup.setInstantiator(new ACSObjectInstantiator() { + public DomainObject doNewInstance(DataObject dataObject) { + return new PortalTab(dataObject); + } + }); + return setup.run(); + + } + + private ResourceType setupSubPortal() { + + ResourceSetup setup = new ResourceSetup(s_log); + + setup.setTitle("SubPortalTab"); + + setup.setResourceObjectType(SubPortalTab.BASE_DATA_OBJECT_TYPE); + + setup.setDescription("A SubPortal Tab!"); + + setup.setInstantiator(new ACSObjectInstantiator() { + public DomainObject doNewInstance(DataObject dataObject) { + return new SubPortalTab(dataObject); + } + }); + return setup.run(); + + } + + private void buildDefaultThemes() { + + Theme theme0 = new Theme("Red Hat"); + theme0.setDescription("A cool corporate theme"); + theme0.setContextBarColor("#E1E1E1"); + theme0.setContextBarTextColor("#3F3F3F"); + theme0.setActiveTabColor("#a21e1e"); + theme0.setInactiveTabColor("#dddddd"); + theme0.setInactiveTabTextColor("#555555"); + theme0.setActiveTabTextColor("#ffffff"); + theme0.setTopRuleColor("#a21e1e"); + theme0.setBottomRuleColor("#a21e1e"); + theme0.setPortletHeaderColor("#a21e1e"); + theme0.setPortletIconColor("#a21e1e"); + theme0.setPortletHeaderTextColor("#ffffff"); + theme0.setPageBGColor("#ffffff"); + theme0.setBodyTextColor("#000000"); + theme0.setNarrowBGColor("#dddddd"); + theme0.save(); +/* + Theme theme1 = new Theme("Celtic Fever"); + theme1.setDescription("A theme for Celtic NBA fans"); + theme1.setContextBarColor("#008800"); + theme1.setActiveTabColor("#008800"); + theme1.setInactiveTabColor("#002200"); + theme1.setInactiveTabTextColor("#ffffff"); + theme1.setActiveTabTextColor("#ffffff"); + theme1.setTopRuleColor("#008800"); + theme1.setBottomRuleColor("#008800"); + theme1.setPortletHeaderColor("#006600"); + theme1.setPortletIconColor("#006600"); + theme1.setPortletHeaderTextColor("#000000"); + theme1.setPageBGColor("#ffffff"); + theme1.setPageBGImage("/assets/cw/workspace/bg_bos.gif"); + theme1.setBodyTextColor("#000000"); + theme1.setNarrowBGColor("#ddeedd"); + theme1.save(); +*/ + Theme theme2 = new Theme("Bright Day"); + theme2.setDescription("A sunny, cloudless sky"); + theme2.setContextBarColor("#003366"); + theme2.setContextBarTextColor("#FFFFFF"); + theme2.setActiveTabColor("#93bee2"); + theme2.setInactiveTabColor("#d8e8f5"); + theme2.setInactiveTabTextColor("#000000"); + theme2.setActiveTabTextColor("#000000"); + theme2.setTopRuleColor("#93bee2"); + theme2.setBottomRuleColor("#93bee2"); + theme2.setPortletHeaderColor("#cccccc"); + theme2.setPortletIconColor("#cccccc"); + theme2.setPortletHeaderTextColor("#000000"); + theme2.setPageBGColor("#ffffff"); + theme2.setPageBGImage(""); + theme2.setNarrowBGColor("#dddddd"); + theme2.setBodyTextColor("#000000"); + + theme2.save(); + + Theme theme3 = new Theme("Harvest"); + theme3.setDescription("High Heat"); + theme3.setContextBarColor("#ff9966"); + theme3.setContextBarTextColor("#ffffff"); + theme3.setActiveTabColor("#ff9966"); + theme3.setInactiveTabColor("#ffcc99"); + theme3.setInactiveTabTextColor("#000000"); + theme3.setActiveTabTextColor("#000000"); + theme3.setTopRuleColor("#ff9966"); + theme3.setBottomRuleColor("#ff9966"); + theme3.setPortletHeaderColor("#ff9966"); + theme3.setPortletIconColor("#ff9966"); + theme3.setPortletHeaderTextColor("#000000"); + theme3.setPageBGColor("#ffffff"); + theme3.setPageBGImage(""); + theme3.setNarrowBGColor("#ffffcc"); + theme3.setBodyTextColor("#000000"); + + theme3.save(); + + Theme theme4 = new Theme("Desert"); + theme4.setDescription("High Heat"); + theme4.setContextBarColor("#cccc99"); + theme4.setContextBarTextColor("#FFFFFF"); + theme4.setActiveTabColor("#cccc99"); + theme4.setInactiveTabColor("#ededca"); + theme4.setInactiveTabTextColor("#000000"); + theme4.setActiveTabTextColor("#000000"); + theme4.setTopRuleColor("#cccc99"); + theme4.setBottomRuleColor("#cccc99"); + theme4.setPortletHeaderColor("#cccc99"); + theme4.setPortletIconColor("#cccc99"); + theme4.setPortletHeaderTextColor("#000000"); + theme4.setPageBGColor("#ffffff"); + theme4.setPageBGImage(""); + theme4.setNarrowBGColor("#ffffcc"); + theme4.setBodyTextColor("#000000"); + + theme4.save(); + + Theme theme5 = new Theme("Stars and Bars"); + theme5.setDescription("Patriotic"); + theme5.setContextBarColor("#cc0000"); + theme5.setContextBarTextColor("#FFFFFF"); + theme5.setActiveTabColor("#cc0000"); + theme5.setInactiveTabColor("#ffffff"); + theme5.setInactiveTabTextColor("#000000"); + theme5.setActiveTabTextColor("#ffffff"); + theme5.setTopRuleColor("#cc0000"); + theme5.setBottomRuleColor("#cc0000"); + theme5.setPortletHeaderColor("#cc0000"); + theme5.setPortletIconColor("#cc0000"); + theme5.setPortletHeaderTextColor("#ffffff"); + theme5.setPageBGColor("#ffffff"); + theme5.setPageBGImage("/assets/cw/backgrounds/stars.gif"); + theme5.setNarrowBGColor("#eeeeee"); + theme5.setBodyTextColor("#000000"); + + theme5.save(); + + } + + public final void doShutdown() {} +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/PortalNavigatorPortlet.java b/ccm-portalserver/src/com/arsdigita/portalserver/PortalNavigatorPortlet.java new file mode 100644 index 000000000..fc6dbe408 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/PortalNavigatorPortlet.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.bebop.BlockStylable; +import com.arsdigita.bebop.GridPanel; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.portal.AbstractPortletRenderer; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.portal.apportlet.AppPortlet; +import com.arsdigita.xml.Element; + +/** + * + * @version $Id: PortalNavigatorPortlet.java pboy $ + */ +public class PortalNavigatorPortlet extends AppPortlet { + + public static final String BASE_DATA_OBJECT_TYPE = + "com.arsdigita.workspace.WorkspaceNavigatorPortlet"; + + @Override + protected String getBaseDataObjectType() { + return BASE_DATA_OBJECT_TYPE; + } + + public PortalNavigatorPortlet(DataObject dataObject) { + super(dataObject); + } + + @Override + protected AbstractPortletRenderer doGetPortletRenderer() { + return new PortalNavigatorPortletRenderer(this); + } +} + +class PortalNavigatorPortletRenderer extends AbstractPortletRenderer { + private PortalNavigatorPortlet m_portlet; + + public PortalNavigatorPortletRenderer + (PortalNavigatorPortlet portlet) { + m_portlet = portlet; + } + + protected void generateBodyXML(PageState pageState, Element parentElement) { + PortalSite currentPortal = + (PortalSite) m_portlet.getParentApplication(); + + if (currentPortal == null) { + return; + } + + GridPanel panel = new GridPanel(2); + + // Variables used cursorwise. + int counter; + String title = null; + String url = null; + + // Parent Portal + + PortalSite portalsite = PortalSite.getPortalSiteForApplication + (currentPortal); + + if (portalsite != null) { + title = portalsite.getTitle(); + url = portalsite.getPrimaryURL(); + panel.add(new Link(title, url)); + Label l = new Label(GlobalizationUtil.globalize("cw.workspace.parent")); + l.setFontWeight(Label.ITALIC); + panel.add(l, BlockStylable.RIGHT); + } + + // Child Portals + + PortalSiteCollection childPortals = + currentPortal.getChildPortalSites(); + + for (counter = 0; childPortals.next(); counter++) { + title = childPortals.getTitle(); + url = childPortals.getPrimaryURL(); + panel.add(new Link(title, url)); + Label l = new Label(GlobalizationUtil.globalize("cw.workspace.child")); + l.setFontWeight(Label.ITALIC); + panel.add(l, BlockStylable.RIGHT); + } + + // Related portals + + PortalSiteCollection relatedPortals = + currentPortal.getRelatedPortalSites(); + + for (counter = 0; relatedPortals.next(); counter++) { + title = relatedPortals.getTitle(); + url = relatedPortals.getPrimaryURL(); + panel.add(new Link(title, url)); + panel.add(new Label("")); + } + + panel.generateXML(pageState, parentElement); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/PortalPage.java b/ccm-portalserver/src/com/arsdigita/portalserver/PortalPage.java new file mode 100644 index 000000000..7d55e806e --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/PortalPage.java @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Container; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.bebop.event.PrintEvent; +import com.arsdigita.bebop.DimensionalNavbar; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.RequestListener; +import com.arsdigita.bebop.event.RequestEvent; + +import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.Party; +import com.arsdigita.kernel.User; + +import com.arsdigita.web.Web; +import com.arsdigita.web.URL; +import com.arsdigita.web.RedirectSignal; + +import com.arsdigita.util.Assert; + +import com.arsdigita.portalserver.personal.PersonalPortal; + +import com.arsdigita.xml.Document; +import com.arsdigita.xml.Element; + + +/** + *

    Experimental

    + * + * @author Justin Ross + * @version $Id: PortalPage.java pboy $ + */ +public class PortalPage extends ApplicationPage { + + protected PortalPage() { + super(); + this.addRequestListener(new RequestListener() { + public void pageRequested(RequestEvent e) { + PageState s = e.getPageState(); + PortalSite psite = + PortalSite.getCurrentPortalSite(s.getRequest()); + if(psite == null) + return; + + if(!psite.isPersonalizable()) + return; + + User user = Web.getContext().getUser(); + if(user == null) + return; + + PortalSiteCollection psc = psite.getAllChildPortalSites(); + PortalSite p = null; + String path; + String fragment; + boolean found = false; + while(psc.next()) { + p = psc.getPortalSite(); + path = p.getPath(); + fragment = path.substring(path.lastIndexOf("/")); + if(fragment.compareTo("/U-" + user.getID().toString()) == 0) + { + found = true; + break; + } + } + if(found) { + throw new RedirectSignal(URL.there(s.getRequest(), + p.getPath()),false); + } + } + }); + } + + // + // Classes for use in generating dynamic labels and links + // + + @Override + protected void buildContextBar() { + DimensionalNavbar navbar = new DimensionalNavbar(); + + navbar.setClassAttr("portalNavbar"); + + navbar.add(new LoggedInLinkWrapper(new PersonalPortalLinkPrinter())); + + // This link will not show up if the current portal is a + // personal portal. + Link current = new Link(new CurrentPortalLinkPrinter()) { + @Override + public boolean isVisible(PageState state) { + PortalSite psite = PortalSite.getCurrentPortalSite + (state.getRequest()); + + return !(psite instanceof PersonalPortal); + } + }; + navbar.add(current); + + navbar.add(new Link(new CurrentApplicationLinkPrinter())); + + getHeader().add(navbar); + } + + @Override + protected void buildGlobal(Container global) { + super.buildGlobal(global); + + //There are four requirements for the customize link + //to be visible: + // 0) The portal must be customizable + // 1) This must not be an admin page + // 2) A user must be logged in + // 3) The user is allowed to customize this portal + // 4) The user does not already have a custom version of this portal + ActionLink personalizable = new ActionLink("Personalize This Portal!") { + @Override + public boolean isVisible(PageState s) { + PortalSite psite = PortalSite.getCurrentPortalSite + (s.getRequest()); + if(psite == null) + return false; + + if(!psite.isPersonalizable()) + return false; //failed req #0 + + String url = Web.getContext().getRequestURL().getRequestURI(); + if(url.endsWith("admin/")) + return false; //failed req #1 + + User user = Web.getContext().getUser(); + if(user == null) + return false; //failed #2 + + //xxx-Need test for req #3 here + + PortalSiteCollection psc = psite.getAllChildPortalSites(); + PortalSite p; + String path; + String fragment; + while(psc.next()) { + p = psc.getPortalSite(); + path = p.getPath(); + fragment = path.substring(path.lastIndexOf("/")); + if(fragment.compareTo("/U-" + user.getID().toString()) == 0) + return false; //failed #4 + } + return true; + } + }; + personalizable.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState s = e.getPageState(); + PortalSite psite = PortalSite.getCurrentPortalSite + (s.getRequest()); + User user = Web.getContext().getUser(); + PortalSite newsite = + PortalSite.createSubPortal(psite, user); + throw new RedirectSignal(URL.there(s.getRequest(), + newsite.getPath()),true); + } + }); + + personalizable.setIdAttr("personalize_link"); + global.add(personalizable); + + } + + protected class PersonalPortalLinkPrinter implements PrintListener { + public PersonalPortalLinkPrinter() {} + + public void prepare(PrintEvent e) { + Link link = (Link) e.getTarget(); + + Party party = Kernel.getContext().getParty(); + + if ( party != null ) { + link.setChild(new Label(GlobalizationUtil.globalize( + "cw.workspace.personal_workspace"))); + link.setTarget("/personal-portal/" + party.getID() + "/"); + } + } + } + + // No need for a PersonalPortalLabelPrinter...yet. + + protected class CurrentPortalLinkPrinter implements PrintListener { + public CurrentPortalLinkPrinter() { + /* Empty */ + } + + public void prepare(PrintEvent e) { + Link link = (Link) e.getTarget(); + PageState state = e.getPageState(); + + PortalSite psite = + PortalSite.getCurrentPortalSite(state.getRequest()); + + if ( psite == null ) { + link.setChild(new Label(GlobalizationUtil.globalize( + "cw.workspace.ecm_administration"))); + link.setTarget("/portal-admin/"); + } else { + link.setChild(new Label(psite.getTitle())); + link.setTarget(psite.getPrimaryURL()); + } + } + } + + protected class CurrentPortalLabelPrinter implements PrintListener { + public CurrentPortalLabelPrinter() { + /* Empty */ + } + + public void prepare(PrintEvent e) { + Label label = (Label) e.getTarget(); + PageState pageState = e.getPageState(); + + PortalSite psite = PortalSite.getCurrentPortalSite + (pageState.getRequest()); + + // Assert.assertNotNull(psite, "PortalSite psite"); + Assert.exists(psite, "PortalSite psite") ; + + label.setLabel(psite.getTitle()); + } + } + + @Override + public void generateXML(PageState state, Document parent) { + super.generateXML(state,parent); + + this.addStyleBlock(state, parent); + } + + public void addStyleBlock(PageState state, Document parent) { + + Theme theme = PortalSite.getCurrentPortalSite(state.getRequest()).getTheme(); + if(theme == null) + { + ThemeCollection themes = Theme.retrieveAllThemes(); + while(themes.next()) + { + theme = themes.getTheme(); + if(theme.getName().equals("Red Hat")) + break; + } + themes.close(); + } + + if(theme == null) + return; + + StringBuffer buffer = theme.buildStyleBlock(); + + Element rootElement = parent.getRootElement(); + + Element styleBlock = rootElement.newChildElement("portalserver:styleblock", + "http://www.redhat.com/portalserver/1.0"); + + styleBlock.setCDATASection(buffer.toString()); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/PortalServerResources.properties b/ccm-portalserver/src/com/arsdigita/portalserver/PortalServerResources.properties new file mode 100644 index 000000000..fc1afa890 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/PortalServerResources.properties @@ -0,0 +1,146 @@ +portalserver.ui.admin.select_theme=Select Theme +portalserver.ui.admin.create_theme=Create A New Theme +portalserver.ui.admin.select_theme_for_portal=Select a theme for this portal +portalserver.ui.admin.create_theme_instruction=Create a theme for this portal +portalserver.ui.admin.lock_column=Lock this column +portalserver.ui.admin.unlock_column=Unlock this column +cw.workspace.none=None +cw.workspace.sign_out=Sign Out +cw.workspace.personal_workspace=Personal Portal +cw.workspace.personal.none=None +cw.workspace.personal.configure_workspace=Configure Portal +cw.workspace.personal.edit_your_profile=Edit Your Profile +cw.workspace.personal.change_your_password=Change Your Password +cw.workspace.personal.site_administration=Site Administration +cw.workspace.personal.personal_workspace=Personal Portal +cw.workspace.administration=Administration +cw.workspace.user_view=User view +cw.workspace.ui.admin.tool_type=Application Type +cw.workspace.ui.admin.edit_props=Editable Properties for +cw.workspace.ui.admin.props=Properties for +cw.workspace.ui.admin.edit_these_props=Edit These Properties +cw.workspace.ui.admin.create=Create +cw.workspace.ui.admin.create_new=Create new +cw.workspace.ui.admin.create_top_level=Create new top level portal +cw.workspace.ui.admin.create_child=Create new child portal +cw.workspace.ui.admin.edit=Edit +cw.workspace.ui.admin.inherit_permissions_prompt=Inherit Permissions from parent workspace? +cw.workspace.ui.admin.inherit_permissions_no=No +cw.workspace.ui.admin.inherit_permissions_yes=Yes + +cw.workspace.ui.admin.title=Title +cw.workspace.ui.admin.mission=Mission +cw.workspace.ui.admin.workspace_basic_properties=Portal Basic Properties +cw.workspace.ui.admin.there_currently_is_no_tab_selected_please_select_a_tab=There currently is no tab selected. Please select a tab. +cw.workspace.ui.admin.new_tab_name=New tab name +cw.workspace.ui.admin.rename_tab=Rename tab +cw.workspace.ui.admin.delete_tab=Delete tab +cw.workspace.ui.admin.shift_left=Shift left +cw.workspace.ui.admin.shift_right= Shift right +cw.workspace.ui.admin.enter_new_name_for_this_tab_in_text_field=Enter new name for this Tab in text field. +cw.workspace.ui.admin.are_you_sure_you_want_to_delete_this_tab=Are you sure you want to delete this tab? +cw.workspace.ui.admin.no_roles_defined=No Roles Defined +cw.workspace.ui.admin.role_name=Role Name: +cw.workspace.ui.admin.assignee_title=Assignee Title: +cw.workspace.ui.admin.null_role=NULL ROLE +cw.workspace.ui.admin.null_assignee_title=NULL Assignee Title +cw.workspace.ui.admin.delete_role=Delete role +cw.workspace.ui.admin.choose_new_or_existing=choose new or existing +cw.workspace.ui.admin.pick_existing=pick existing +cw.workspace.ui.admin.you_have_opted_to_display_an_existing=You have opted to display an existing +cw.workspace.ui.admin.apptype=apptype +cw.workspace.ui.admin.in_the_new_portlet= in the new portlet. +cw.workspace.ui.admin.choose_one_of_the=Choose one of the +cw.workspace.ui.admin.already_in_this_workspace= already in this portal. +cw.workspace.ui.admin.you_chose_to_create_a_new=You chose to create a new +cw.workspace.ui.admin.portlet= portlet. +cw.workspace.ui.admin.no_linked_workspaces=No Linked Portals +cw.workspace.ui.admin.no_child_workspaces=No Child Portals +cw.workspace.ui.admin.child_workspace_info=Child Portal Info +cw.workspace.ui.admin.go_to_this_workspace=Go to this portal +cw.workspace.ui.admin.administer_this_workspace=Administer this portal +cw.workspace.ui.admin.linked_workspace_info=Linked Portal Info +cw.workspace.ui.admin.configure_workspace=Configure Portal +cw.workspace.ui.admin.return_to_workspace=Return to Portal +cw.workspace.ui.admin.parent_workspace=Parent Portal +cw.workspace.ui.admin.none=None +cw.workspace.ui.admin.url_fragment=URL Fragment: +cw.workspace.ui.admin.select_parent_workspace=Select Parent Workspace: +cw.workspace.ui.admin.personalize=Allow Personalized SubPortals to be created from this Portal +cw.workspace.ui.admin.unpersonalize=Disallow Personalized SubPortals to be created from this Portal +cw.workspace.ui.admin.view=view +cw.workspace.ui.admin.viewpanel_header=View +cw.workspace.ui.admin.modifypanel_header=Modify +cw.workspace.ui.admin.deletepanel_header=Delete +cw.workspace.ui.admin.delete_table_header1=(check to delete) +cw.workspace.ui.admin.delete_table_header2=Application Name +cw.workspace.ui.admin.delete_table_header3=Application Type +cw.workspace.ui.admin.delete_instruction1=This form provides a means for deleting Portals and mounting an informational message at the deleted Portal's URL. +cw.workspace.ui.select_a_bookmark_for_editing=Select a Bookmark for editing +cw.workspace.ui.name_of_new_bookmark=Name of New Bookmark: +cw.workspace.ui.new_bookmark_url=New Bookmark URL: +cw.workspace.ui.bookmark_description=Bookmark Description: +cw.workspace.ui.delete_this_bookmark=Delete this Bookmark +cw.workspace.ui.edit_fields_and_click_save_button=Edit fields and click save button. +cw.workspace.ui.bookmark_name=Bookmark Name: +cw.workspace.ui.bookmark_url=Bookmark URL: +cw.workspace.ui.creation_date=Creation Date: +cw.workspace.ui.last_modified_date=Last Modified Date: +cw.workspace.ui.created_by=Created by: +cw.workspace.ui.number_of_visits_by_this_workspace=Number of visits by this Workspace: +cw.workspace.ui.modification_date=Modification Date +cw.workspace.ui.creator=Creator +cw.workspace.ui.are_you_sure_you_want_to_delete_this_bookmark=Are you sure you want to delete this Bookmark? +cw.workspace.ui.no_participants=No Participants +cw.workspace.ui.roles=Roles +cw.workspace.ui.enter_first_name_last_name_andor_email_address=Enter first name, last name and/or email address: +cw.workspace.ui.no_matches_found=No matches found +cw.workspace.ui.select_user_or_group_to_add=Select user or group to add: +cw.workspace.ui.participant_info=Participant Info +cw.workspace.ui.participant_roles=Participant Roles +cw.workspace.ui.enter_search_criteria=Enter Search Criteria +cw.workspace.ui.configure_workspace=Configure Portal +cw.workspace.ui.personal_workspace=Personal Portal +cw.workspace.ui.participants=Participants +cw.workspace.parent=parent +cw.workspace.child=child +cw.workspace.ecm_administration=Portal Administration +cw.workspace.mission=Mission +cw.workspace.search_participants=Search participants +cw.workspace.participants=Participants +cw.workspace.ui.admin.archive=Archive +cw.workspace.ui.admin.unarchive=Un-Archive +cw.workspace.ui.admin.bring_online=Bring Online +cw.workspace.ui.admin.update=Update Properties +cw.workspace.ui.admin.cancel=Cancel +cw.workspace.ui.admin.delete=Delete +cw.workspace.ui.admin.visit=Visit +cw.workspace.ui.admin.is_archived=Currently Archived Since +cw.workspace.ui.admin.is_online=Currently Online +cw.workspace.ui.admin.is_draft=Draft Version - Not Online +cw.workspace.ui.admin.archive_this_portal=Do you really want to Archive this Portal? +cw.workspace.ui.admin.online_this_portal=Do you really want to bring this Archived Portal online? +cw.workspace.ui.admin.delete_this_portal=Do you really want to delete this Portal? +cw.workspace.ui.admin.portals_currently_archived=Portals Currently Archived: +cw.workspace.ui.admin.portals_currently_online=Portals Currently Online: +cw.workspace.ui.admin.portals_currently_mounted=Portals Currently Mounted: +cw.workspace.ui.admin.online_portal_name=Portal Name +cw.workspace.ui.admin.portal_name=Portal Name: +cw.workspace.ui.admin.portal_url=Portal URL: +cw.workspace.ui.admin.portal_status=Portal Status: +cw.workspace.ui.admin.portal_desc=Portal Mission: +cw.workspace.ui.admin.need_portal_name=Every Portal must have a name +cw.workspace.ui.admin.portal_creation_date=Portal Creation Date: +cw.workspace.ui.admin.archive_portal_name=Archived Portal Name +cw.workspace.ui.admin.archive_creation_date=Archived since: +cw.workspace.ui.admin.portal_panel_header=System Portal List: +cw.workspace.ui.admin.portal_archive_header=Select a Portal +cw.workspace.ui.admin.no_portal_selected=No Portal Selected +cw.workspace.ui.admin.empty_archive=Currently no archived portals +cw.workspace.ui.admin.empty_online=Currently no online portals +cw.workspace.ui.admin.recurse_archive=Check here if you would like to recursively archive all child portals of this portal +cw.workspace.ui.admin.empty_sitemap=Currently no portals +cw.workspace.ui.email=Email +cw.workspace.ui.name=Name +cw.workspace.ui.roles=Roles +cw.workspace.ui.admin. diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/PortalServerResources_de.properties b/ccm-portalserver/src/com/arsdigita/portalserver/PortalServerResources_de.properties new file mode 100644 index 000000000..fc1afa890 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/PortalServerResources_de.properties @@ -0,0 +1,146 @@ +portalserver.ui.admin.select_theme=Select Theme +portalserver.ui.admin.create_theme=Create A New Theme +portalserver.ui.admin.select_theme_for_portal=Select a theme for this portal +portalserver.ui.admin.create_theme_instruction=Create a theme for this portal +portalserver.ui.admin.lock_column=Lock this column +portalserver.ui.admin.unlock_column=Unlock this column +cw.workspace.none=None +cw.workspace.sign_out=Sign Out +cw.workspace.personal_workspace=Personal Portal +cw.workspace.personal.none=None +cw.workspace.personal.configure_workspace=Configure Portal +cw.workspace.personal.edit_your_profile=Edit Your Profile +cw.workspace.personal.change_your_password=Change Your Password +cw.workspace.personal.site_administration=Site Administration +cw.workspace.personal.personal_workspace=Personal Portal +cw.workspace.administration=Administration +cw.workspace.user_view=User view +cw.workspace.ui.admin.tool_type=Application Type +cw.workspace.ui.admin.edit_props=Editable Properties for +cw.workspace.ui.admin.props=Properties for +cw.workspace.ui.admin.edit_these_props=Edit These Properties +cw.workspace.ui.admin.create=Create +cw.workspace.ui.admin.create_new=Create new +cw.workspace.ui.admin.create_top_level=Create new top level portal +cw.workspace.ui.admin.create_child=Create new child portal +cw.workspace.ui.admin.edit=Edit +cw.workspace.ui.admin.inherit_permissions_prompt=Inherit Permissions from parent workspace? +cw.workspace.ui.admin.inherit_permissions_no=No +cw.workspace.ui.admin.inherit_permissions_yes=Yes + +cw.workspace.ui.admin.title=Title +cw.workspace.ui.admin.mission=Mission +cw.workspace.ui.admin.workspace_basic_properties=Portal Basic Properties +cw.workspace.ui.admin.there_currently_is_no_tab_selected_please_select_a_tab=There currently is no tab selected. Please select a tab. +cw.workspace.ui.admin.new_tab_name=New tab name +cw.workspace.ui.admin.rename_tab=Rename tab +cw.workspace.ui.admin.delete_tab=Delete tab +cw.workspace.ui.admin.shift_left=Shift left +cw.workspace.ui.admin.shift_right= Shift right +cw.workspace.ui.admin.enter_new_name_for_this_tab_in_text_field=Enter new name for this Tab in text field. +cw.workspace.ui.admin.are_you_sure_you_want_to_delete_this_tab=Are you sure you want to delete this tab? +cw.workspace.ui.admin.no_roles_defined=No Roles Defined +cw.workspace.ui.admin.role_name=Role Name: +cw.workspace.ui.admin.assignee_title=Assignee Title: +cw.workspace.ui.admin.null_role=NULL ROLE +cw.workspace.ui.admin.null_assignee_title=NULL Assignee Title +cw.workspace.ui.admin.delete_role=Delete role +cw.workspace.ui.admin.choose_new_or_existing=choose new or existing +cw.workspace.ui.admin.pick_existing=pick existing +cw.workspace.ui.admin.you_have_opted_to_display_an_existing=You have opted to display an existing +cw.workspace.ui.admin.apptype=apptype +cw.workspace.ui.admin.in_the_new_portlet= in the new portlet. +cw.workspace.ui.admin.choose_one_of_the=Choose one of the +cw.workspace.ui.admin.already_in_this_workspace= already in this portal. +cw.workspace.ui.admin.you_chose_to_create_a_new=You chose to create a new +cw.workspace.ui.admin.portlet= portlet. +cw.workspace.ui.admin.no_linked_workspaces=No Linked Portals +cw.workspace.ui.admin.no_child_workspaces=No Child Portals +cw.workspace.ui.admin.child_workspace_info=Child Portal Info +cw.workspace.ui.admin.go_to_this_workspace=Go to this portal +cw.workspace.ui.admin.administer_this_workspace=Administer this portal +cw.workspace.ui.admin.linked_workspace_info=Linked Portal Info +cw.workspace.ui.admin.configure_workspace=Configure Portal +cw.workspace.ui.admin.return_to_workspace=Return to Portal +cw.workspace.ui.admin.parent_workspace=Parent Portal +cw.workspace.ui.admin.none=None +cw.workspace.ui.admin.url_fragment=URL Fragment: +cw.workspace.ui.admin.select_parent_workspace=Select Parent Workspace: +cw.workspace.ui.admin.personalize=Allow Personalized SubPortals to be created from this Portal +cw.workspace.ui.admin.unpersonalize=Disallow Personalized SubPortals to be created from this Portal +cw.workspace.ui.admin.view=view +cw.workspace.ui.admin.viewpanel_header=View +cw.workspace.ui.admin.modifypanel_header=Modify +cw.workspace.ui.admin.deletepanel_header=Delete +cw.workspace.ui.admin.delete_table_header1=(check to delete) +cw.workspace.ui.admin.delete_table_header2=Application Name +cw.workspace.ui.admin.delete_table_header3=Application Type +cw.workspace.ui.admin.delete_instruction1=This form provides a means for deleting Portals and mounting an informational message at the deleted Portal's URL. +cw.workspace.ui.select_a_bookmark_for_editing=Select a Bookmark for editing +cw.workspace.ui.name_of_new_bookmark=Name of New Bookmark: +cw.workspace.ui.new_bookmark_url=New Bookmark URL: +cw.workspace.ui.bookmark_description=Bookmark Description: +cw.workspace.ui.delete_this_bookmark=Delete this Bookmark +cw.workspace.ui.edit_fields_and_click_save_button=Edit fields and click save button. +cw.workspace.ui.bookmark_name=Bookmark Name: +cw.workspace.ui.bookmark_url=Bookmark URL: +cw.workspace.ui.creation_date=Creation Date: +cw.workspace.ui.last_modified_date=Last Modified Date: +cw.workspace.ui.created_by=Created by: +cw.workspace.ui.number_of_visits_by_this_workspace=Number of visits by this Workspace: +cw.workspace.ui.modification_date=Modification Date +cw.workspace.ui.creator=Creator +cw.workspace.ui.are_you_sure_you_want_to_delete_this_bookmark=Are you sure you want to delete this Bookmark? +cw.workspace.ui.no_participants=No Participants +cw.workspace.ui.roles=Roles +cw.workspace.ui.enter_first_name_last_name_andor_email_address=Enter first name, last name and/or email address: +cw.workspace.ui.no_matches_found=No matches found +cw.workspace.ui.select_user_or_group_to_add=Select user or group to add: +cw.workspace.ui.participant_info=Participant Info +cw.workspace.ui.participant_roles=Participant Roles +cw.workspace.ui.enter_search_criteria=Enter Search Criteria +cw.workspace.ui.configure_workspace=Configure Portal +cw.workspace.ui.personal_workspace=Personal Portal +cw.workspace.ui.participants=Participants +cw.workspace.parent=parent +cw.workspace.child=child +cw.workspace.ecm_administration=Portal Administration +cw.workspace.mission=Mission +cw.workspace.search_participants=Search participants +cw.workspace.participants=Participants +cw.workspace.ui.admin.archive=Archive +cw.workspace.ui.admin.unarchive=Un-Archive +cw.workspace.ui.admin.bring_online=Bring Online +cw.workspace.ui.admin.update=Update Properties +cw.workspace.ui.admin.cancel=Cancel +cw.workspace.ui.admin.delete=Delete +cw.workspace.ui.admin.visit=Visit +cw.workspace.ui.admin.is_archived=Currently Archived Since +cw.workspace.ui.admin.is_online=Currently Online +cw.workspace.ui.admin.is_draft=Draft Version - Not Online +cw.workspace.ui.admin.archive_this_portal=Do you really want to Archive this Portal? +cw.workspace.ui.admin.online_this_portal=Do you really want to bring this Archived Portal online? +cw.workspace.ui.admin.delete_this_portal=Do you really want to delete this Portal? +cw.workspace.ui.admin.portals_currently_archived=Portals Currently Archived: +cw.workspace.ui.admin.portals_currently_online=Portals Currently Online: +cw.workspace.ui.admin.portals_currently_mounted=Portals Currently Mounted: +cw.workspace.ui.admin.online_portal_name=Portal Name +cw.workspace.ui.admin.portal_name=Portal Name: +cw.workspace.ui.admin.portal_url=Portal URL: +cw.workspace.ui.admin.portal_status=Portal Status: +cw.workspace.ui.admin.portal_desc=Portal Mission: +cw.workspace.ui.admin.need_portal_name=Every Portal must have a name +cw.workspace.ui.admin.portal_creation_date=Portal Creation Date: +cw.workspace.ui.admin.archive_portal_name=Archived Portal Name +cw.workspace.ui.admin.archive_creation_date=Archived since: +cw.workspace.ui.admin.portal_panel_header=System Portal List: +cw.workspace.ui.admin.portal_archive_header=Select a Portal +cw.workspace.ui.admin.no_portal_selected=No Portal Selected +cw.workspace.ui.admin.empty_archive=Currently no archived portals +cw.workspace.ui.admin.empty_online=Currently no online portals +cw.workspace.ui.admin.recurse_archive=Check here if you would like to recursively archive all child portals of this portal +cw.workspace.ui.admin.empty_sitemap=Currently no portals +cw.workspace.ui.email=Email +cw.workspace.ui.name=Name +cw.workspace.ui.roles=Roles +cw.workspace.ui.admin. diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/PortalServlet.java b/ccm-portalserver/src/com/arsdigita/portalserver/PortalServlet.java new file mode 100644 index 000000000..8c6ccfca2 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/PortalServlet.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + +import com.arsdigita.bebop.Page; +import com.arsdigita.persistence.TransactionContext; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.portalserver.ui.PortalHomePage; +import com.arsdigita.portalserver.ui.PortalParticipants; +import com.arsdigita.portalserver.ui.admin.PortalAdminPage; +import com.arsdigita.templating.PresentationManager; +import com.arsdigita.templating.Templating; +import com.arsdigita.web.Application; +import com.arsdigita.web.BaseApplicationServlet; +import com.arsdigita.xml.Document; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; + +/** + * + * @author Justin Ross <jross@redhat.com> + * @version $Id: PortalServlet.java pboy $ + */ +public class PortalServlet extends BaseApplicationServlet { + + private static final Logger s_log = Logger.getLogger + (PortalServlet.class); + + private static final PresentationManager s_presManager = + Templating.getPresentationManager(); + + private static Page s_homePage = new PortalHomePage(); + private static Page s_particPage = PortalParticipants.createPage(); + private static Page s_adminPage = null; + + static { + TransactionContext ctx = SessionManager.getSession().getTransactionContext(); + ctx.beginTxn(); + + s_adminPage = new PortalAdminPage(); + + ctx.commitTxn(); + } + + public void doService(HttpServletRequest sreq, + HttpServletResponse sresp, + Application app) + throws ServletException, IOException { + s_log.debug("PortalServlet.doService called for request '" + + sreq.getRequestURI() + "'"); + + String path = sreq.getServletPath(); + Document doc = null; + + if (path.endsWith("participants")) { + doc = s_particPage.buildDocument(sreq, sresp); + } else if (path.endsWith("admin")) { + doc = s_adminPage.buildDocument(sreq, sresp); + } else { + doc = s_homePage.buildDocument(sreq, sresp); + } + + s_presManager.servePage(doc, sreq, sresp); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/PortalSite.java b/ccm-portalserver/src/com/arsdigita/portalserver/PortalSite.java new file mode 100644 index 000000000..8f287e1f7 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/PortalSite.java @@ -0,0 +1,1087 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.kernel.Group; +import com.arsdigita.kernel.Party; +import com.arsdigita.kernel.PartyCollection; +import com.arsdigita.kernel.Resource; +import com.arsdigita.kernel.SiteNode; +import com.arsdigita.kernel.User; +import com.arsdigita.kernel.permissions.PermissionDescriptor; +import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; +import com.arsdigita.persistence.DataAssociation; +import com.arsdigita.persistence.DataAssociationCursor; +import com.arsdigita.persistence.DataCollection; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.DataQuery; +import com.arsdigita.persistence.DataQueryDataCollectionAdapter; +import com.arsdigita.persistence.OID; +import com.arsdigita.persistence.SessionManager; +// import com.arsdigita.persistence.Filter; +// import com.arsdigita.persistence.PersistenceException; +import com.arsdigita.persistence.Filter; +import com.arsdigita.portal.apportlet.AppPortlet; +import com.arsdigita.portal.Portlet; +import com.arsdigita.portal.AgentPortlet; +import com.arsdigita.portal.PortletCollection; +import com.arsdigita.util.Assert; +import com.arsdigita.web.Application; +import com.arsdigita.web.ApplicationCollection; +import com.arsdigita.web.ApplicationType; + +import java.math.BigDecimal; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Iterator; +import java.util.LinkedList; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.log4j.Category; + +/** + *

    A PortalSite is a mountable Portal instance, complete + * with URL. A PortalSite is made up of one or more PortalTabs. + * A PortalTab is in turn comprised of zero or more Portlets.

    + * + *

    A PortalSite presents what the User considers to be + * a "Portal". For the sake of clarity, however, in the source code side + * of things, a Portal is actually a domain class in CCM Core, + * used as a foundation class by PortalSite.

    + * + * @author Justin Ross + * @author Archit Shah + * @author Jim Parsons + * @version $Id: portalserver/PortalSite.java pboy $ + */ +public class PortalSite extends Application { + + /** Logger instance for debugging */ + private static Category s_log = Category.getInstance(PortalSite.class); + + public static final String BASE_DATA_OBJECT_TYPE = + "com.arsdigita.workspace.Workspace"; + + private static final String PARTICIPANT_ID_QUERY = + "com.arsdigita.workspace.WorkspaceParticipantIDs"; + + private static final int SORT_KEY_JUMP = 10; + + private Role m_memberRole; + private boolean m_wasNew = false; + + /** + * + * @return + */ + @Override + protected String getBaseDataObjectType() { + return BASE_DATA_OBJECT_TYPE; + } + + /** + * Constructor for PortalSite. Access is protected. Use a + * createPortalSite() method for a new PortalSite object. + */ + protected PortalSite(DataObject dataObject) { + super(dataObject); + } + + @Override + protected void initialize() { + super.initialize(); + + if (isNew()) { + + setReady(false); + + setDraft(false); + + setPersonalizable(false); + + setUnarchived(); + + setCreationDate(); + } + } + + public static PortalSite createPortalSite + (String urlName, String title, PortalSite parent, + boolean inheritPermissions) { + + ApplicationType type = + ApplicationType.retrieveApplicationTypeForApplication + (BASE_DATA_OBJECT_TYPE); + + PortalSite ps = (PortalSite) Application.createApplication + (type, urlName, title, parent); + + ps.setUnarchived(); + ps.setDraft(false); + ps.setCreationDate(); + ps.setPersonalizable(false); + + if (!inheritPermissions) { + PermissionService.setContext(ps, null); + } + + return ps; + } + + + /** + * Creates an Instance ot ApplicationType PortalSite as a legacy free + * application. + * @param urlName + * @param title + * @param parent + * @return + */ + public static PortalSite createPortalSite(String urlName, + String title, + PortalSite parent) { + + ApplicationType type = + ApplicationType.retrieveApplicationTypeForApplication + (BASE_DATA_OBJECT_TYPE); + + PortalSite ps = (PortalSite) Application.createApplication + (type, urlName, title, parent); + + ps.setUnarchived(); + + ps.setDraft(false); + + ps.setCreationDate(); + + ps.setPersonalizable(false); + + return ps; + + } + + /** + * @deprecated Use PortalSite.retrieveAllPortalSites(). + */ + public static PortalSiteCollection retrieveAll() { + return PortalSite.retrieveAllPortalSites(); + } + + /** + * Returns a collection of all PortalSite's currently mounted on + * the server. Cannot return null. The collection returned includes + * archived portals as well. Most applications will want to call + * retrieveAllActivePortalSites() + */ + public static PortalSiteCollection retrieveAllPortalSites() { + DataCollection dataCollection = + SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE); + + PortalSiteCollection portalsiteCollection = new PortalSiteCollection + (dataCollection); + + return portalsiteCollection; + } + + /** + * Returns a collection of all active PortalSite's currently mounted on + * the server. Cannot return null. The collection returned does not include + * archived portals. + */ + public static PortalSiteCollection retrieveAllActivePortalSites() { + DataCollection dataCollection = + SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE); + + PortalSiteCollection portalsiteCollection = new PortalSiteCollection + (dataCollection); + + portalsiteCollection.filterForArchived(); + + return portalsiteCollection; + } + + /** + * + * @param siteNode + * @return Can return null. + */ +/* OBVIOUSLY NO LONGER USED + public static PortalSite retrievePortalSiteForSiteNode(SiteNode siteNode) { + DataQuery query = SessionManager.getSession().retrieveQuery + ("com.arsdigita.workspace.workspaceForSiteNodeID"); + + query.setParameter("siteNodeID", siteNode.getID()); + + PortalSite portalsite = null; + + if (query.next()) { + DataObject dataObject = (DataObject) query.get("workspace"); + portalsite = PortalSite.retrievePortalSite(dataObject); + } + + query.close(); + + return portalsite; + } +*/ + // Can return null. + public static PortalSite retrievePortalSite(BigDecimal id) { + return (PortalSite) Application.retrieveApplication(id); + } + + // Can return null. + public static PortalSite retrievePortalSite(OID oid) { + return (PortalSite) Application.retrieveApplication(oid); + } + + // Can return null. + public static PortalSite retrievePortalSite(DataObject dataObject) { + return (PortalSite) Application.retrieveApplication(dataObject); + } + + @Override + protected void beforeSave() { + m_wasNew = isNew(); + + super.beforeSave(); + + } + + @Override + protected void afterSave() { + super.afterSave(); + + if (m_wasNew) { + Role role = Role.createRole + (this, "Members", "Member", "", true, Role.MEMBER_TYPE); + setMemberRole(role); + role.save(); + + PermissionService.grantPermission + (new PermissionDescriptor + (PrivilegeDescriptor.READ, this, getMemberRole())); + + PortalSite parent = getPortalSiteForApplication(this); + + if (parent != null) { + parent.addMember(getMemberRole()); + parent.save(); + } + + m_wasNew = false; + } + } + + //protected void beforeDelete() { + @Override + public void beforeDelete() { + //First, make certain that portalsite to be deleted has no children + PortalSiteCollection psc = getAllChildPortalSites(); + if(!psc.isEmpty()) + throw new UnsupportedOperationException + ("Deletion of PortalSites does not support recursion: you" + + "must delete children of this portal site first."); + + } + + // + // Association properties + // + + public ApplicationCollection getFullPagePortalSiteApplications() { + ApplicationCollection applications = getChildApplications(); + + applications.filterToPortalSiteApplications(); + applications.filterToHasFullPageView(); + + return applications; + } + + /** + * This method is used by portlet create and app create form flow + * to determine if an apptype is already present for a PortalSite. + */ + public boolean isAppTypeInPortalSite(ApplicationType appType) { + ApplicationCollection apps = getFullPagePortalSiteApplications(); + ApplicationType atp; + + while (apps.next()) { + atp = apps.getApplication().getApplicationType(); + + if (atp.getID().equals(appType.getID())) { + apps.close(); + return true; + } + } + + apps.close(); + + return false; + } + + public PortalSiteCollection getChildPortalSites() { + DataQuery query = SessionManager.getSession().retrieveQuery + ("com.arsdigita.workspace.childWorkspacesForApplicationID"); + + query.setParameter("applicationID", getID()); + + DataCollection collection = + new DataQueryDataCollectionAdapter(query, "workspace"); + + query.close(); + + PortalSiteCollection psc = new PortalSiteCollection(collection); + + psc.filterForUnarchived(); + + return psc; + } + + public PortalSiteCollection getAllChildPortalSites() { + DataQuery query = SessionManager.getSession().retrieveQuery + ("com.arsdigita.workspace.childWorkspacesForApplicationID"); + + query.setParameter("applicationID", getID()); + + DataCollection collection = + new DataQueryDataCollectionAdapter(query, "workspace"); + + query.close(); + + return new PortalSiteCollection(collection); + } + + public PortalSiteCollection getRelatedPortalSites() { + DataAssociation association = (DataAssociation) get("relatedWorkspace"); + + PortalSiteCollection psc = + new PortalSiteCollection(association.cursor()); + psc.filterForUnarchived(); + return psc; + } + + public PortalSiteCollection getAllRelatedPortalSites() { + DataAssociation association = (DataAssociation) get("relatedWorkspace"); + + PortalSiteCollection psc = + new PortalSiteCollection(association.cursor()); + return psc; + } + + public static PortalSite getPortalSiteForApplication(Application app) { + Application application = app.getParentApplication(); + + if (application == null) { + return null; + } + + // Sometimes a Portalsite has an ordinary application as its + // parent. This is true, for instance, of personal + // portals. In these cases we return null, because there + // is no parent *Portal*. + + if (!(application instanceof PortalSite)) { + return null; + } + + return (PortalSite) application; + } + + public static PortalSite getPortalSiteForAppPortlet(AppPortlet portlet) { + Resource parentRes = portlet.getParentResource(); + + if (parentRes == null) { + return null; + } + + //Now we have (possibly) the parent application of the portlet... + + if (!(parentRes instanceof Application)) { + return null; + } + + //if the parent of this portlet is the PortalSite, return the PortalSite. + //otherwise, try to fetch the parent application's parent PortalSite + if (parentRes instanceof PortalSite) { + return (PortalSite)parentRes; + } else { + return getPortalSiteForApplication((Application)parentRes); + } + } + + // Can return null. + public static PortalSite getCurrentPortalSite(HttpServletRequest request) { + String key = "com.arsdigita.workspace.Workspace.currentWorkspace"; + + PortalSite currentPortalSite = null; + + synchronized (request) { + currentPortalSite = (PortalSite) request.getAttribute(key); + + if (currentPortalSite == null) { + currentPortalSite = doGetCurrentPortalSite(request); + + request.setAttribute(key, currentPortalSite); + } + } + + return currentPortalSite; + } + + private static PortalSite + doGetCurrentPortalSite(HttpServletRequest request) { + // First, assume that the user is at a PortalSite already, + // since we can save a query if we're right. This logic will + // not make sense if we find that this method is called mostly + // from sub applications of a portal site, since it incurs an + // extra query in that case. + + Application application = Application.getCurrentApplication(request); + + if (application instanceof PortalSite) { + return (PortalSite) application; + } + + while (true) { + if (application == null) { + return null; + } + + application = application.getParentApplication(); + + if (application instanceof PortalSite) { + return (PortalSite) application; + } + } + } + + public static PortalSiteCollection getRootPortalSites() { + DataQuery query = SessionManager.getSession().retrieveQuery + ("com.arsdigita.workspace.rootWorkspaces"); + + DataCollection collection = + new DataQueryDataCollectionAdapter(query, "workspace"); + + query.close(); + + PortalSiteCollection psc = new PortalSiteCollection(collection); + + psc.filterForUnarchived(); + + return psc; + } + + public static PortalSiteCollection getAllRootPortalSites() { + DataQuery query = SessionManager.getSession().retrieveQuery + ("com.arsdigita.workspace.rootWorkspaces"); + Application app = + Application.retrieveApplicationForPath("/personal-portal/"); + + if (app != null) + query.setParameter("parentID",app.getID()); + + DataCollection collection = + new DataQueryDataCollectionAdapter(query, "workspace"); + + query.close(); + + return new PortalSiteCollection(collection); + } + + public void addRelatedPortalSite(PortalSite portalsite) { + add("relatedWorkspace", portalsite); + } + + public void removeRelatedPortalSite(PortalSite portalsite) { + remove("relatedWorkspace", portalsite); + } + + public boolean isDirectParticipant(Party party) { + DataAssociationCursor dac = + ((DataAssociation) get("participants")).cursor(); + dac.addEqualsFilter("id", party.getID()); + if (dac.size() == 0) { + return false; + } else { + return true; + } + } + + public boolean isParticipant(Party party) { + throw new UnsupportedOperationException(); + } + + public boolean isDirectMember(Party party) { + Group g = getMemberRole(); + return g.hasDirectMemberOrSubgroup(party); + } + + public boolean isMember(Party party) { + Group g = getMemberRole(); + if (party instanceof User) { + return g.hasMember((User) party); + } else if (party instanceof Group) { + return g.hasSubgroup((Group) party); + } else { + throw new IllegalArgumentException( + "party must be a user or a group"); + } + } + + /** + * add a participant as a member, the party should not already be a + * participant. adds specified party to member group, and makes the + * specified party a participant + **/ + public void addMember(Party member) { + addParticipant(member); + Group g = getMemberRole(); + if (member instanceof User) { + User u = (User) member; + g.addMember(u); + } else if (member instanceof Group) { + Group pGroup = (Group) member; + g.addSubgroup(pGroup); + } else { + throw new IllegalArgumentException( + "party must be a user or a group"); + } + } + + /** + * Adds participant and grants participant read privilege on the workspace. + **/ + public void addParticipant(Party participant) { + addParticipant(participant, true); + } + + /** + * Adds participant and optionally grants participant read privilege on + * the PortalSite. + * + * @param addDefaultPriv whether or not the read privilege should be + * granted + **/ + public void addParticipant(Party participant, boolean addDefaultPriv) { + add("participants", participant); + if (addDefaultPriv) { + PermissionService.grantPermission(new PermissionDescriptor( + PrivilegeDescriptor.READ, this, participant)); + } + } + + /** + * remove a participant or member from workspace and revoke privileges on + * the Portal Site + **/ + public void removeParticipant(Party participant) { + RoleCollection rc = getRoles(); + if (participant instanceof User) { + while (rc.next()) { + Role r = rc.getRole(); + r.removeMember((User) participant); + r.save(); + } + } else if (participant instanceof Group) { + while (rc.next()) { + Role r = rc.getRole(); + r.removeSubgroup((Group) participant); + r.save(); + } + } else { + throw new IllegalArgumentException( + "received party that was neither user nor group"); + } + + remove("participants", participant); + + // revoke direct grants on this + for (Iterator privIter = PermissionService.getDirectPrivileges + (getOID(), participant.getOID()); + privIter.hasNext(); ) { + PrivilegeDescriptor priv = (PrivilegeDescriptor) privIter.next(); + PermissionService.revokePermission + (new PermissionDescriptor(priv, this, participant)); + } + + // revoke direct grants on applications in the portalsite + ApplicationCollection ac = getFullPagePortalSiteApplications(); + while (ac.next()) { + OID appOID = new OID(ac.getSpecificObjectType(), ac.getID()); + Iterator appPrivs = PermissionService.getDirectPrivileges + (appOID, participant.getOID()); + while (appPrivs.hasNext()) { + PrivilegeDescriptor priv = (PrivilegeDescriptor) appPrivs.next(); + PermissionService.revokePermission + (new PermissionDescriptor( + priv, appOID, participant.getOID())); + } + } + } + + public PartyCollection getParticipants() { + return new PartyCollection( + ((DataAssociation) get("participants")).cursor()); + } + + + public long getParticipantCount() { + return ((DataAssociation)get("participants")).cursor().size(); + } + + + public PartyCollection getNonParticipants() { + DataCollection dc = + SessionManager.getSession() + .retrieve("com.arsdigita.kernel.Party"); + Filter f = dc.addNotInSubqueryFilter("id", PARTICIPANT_ID_QUERY); + f.set("workspaceID", getID()); + return new PartyCollection(dc); + } + + + /** + *

    Get a collection of all participants in the Portal Site whose + * initial (see {@link getParticipantInitials + * getParticipantInitials} for a definition of a participant's + * initial) is the specified value.

    + * + * @param initial Single-character string, must be uppercase + **/ + public PartyCollection getParticipantsWithInitial(String initial) { + // Assert.assertNotNull(initial); + Assert.exists(initial); + // Assert.assertTrue(initial.length() == 1, "Initial needs length 1"); + Assert.isTrue(initial.length() == 1, "Initial needs length 1"); + // Assert.assertTrue(initial.equals(initial.toUpperCase()), + Assert.isTrue(initial.equals(initial.toUpperCase()), + "Initial must be uppercase"); + + DataAssociationCursor dac = + ((DataAssociation)get("participants")).cursor(); + Filter f = dac.addInSubqueryFilter + ("id", "com.arsdigita.workspace.WorkspaceParticipantsWithInitial"); + f.set("workspaceID", getID()); + f.set("nameInitial", initial); + + return new PartyCollection(dac); + } + + /** + * Returns the member role. This role can be modified directly to change + * the parties in the role. + **/ + public Role getMemberRole() { + if (m_memberRole == null) { + DataAssociation roles = (DataAssociation) get("roles"); + DataAssociationCursor rolesCursor + = roles.getDataAssociationCursor(); + rolesCursor.addEqualsFilter("type", Role.MEMBER_TYPE); + + if ( rolesCursor.next() ) { + m_memberRole = (Role) DomainObjectFactory. + newInstance(rolesCursor.getDataObject()); + } + + rolesCursor.close(); + } + + return m_memberRole; + } + + private void setMemberRole(Role role) { + m_memberRole = role; + } + + /** + * Returns the collection of roles in this portal site. The returned roles + * can be modified directly to change the parties assigned to each role. + **/ + public RoleCollection getRoles() { + return new RoleCollection( + ((DataAssociation) get("roles")).cursor(), this); + } + + public RoleCollection getDirectRolesFor(Party p) { + DataAssociationCursor dac = ((DataAssociation) get("roles")).cursor(); + if (p instanceof User) { + Filter f = dac.addInSubqueryFilter( + "id", "com.arsdigita.workspace.DirectRolesForUser"); + f.set("participantID", p.getID()); + } else if (p instanceof Group) { + Filter f = dac.addInSubqueryFilter( + "id", "com.arsdigita.workspace.DirectRolesForGroup"); + f.set("participantID", p.getID()); + } else { + throw new IllegalArgumentException( + "received party that was neither user nor group"); + } + return new RoleCollection(dac); + } + + /** + * Returns the collection of roles in this workspace that the specified + * party is contained in. + **/ + public RoleCollection getRolesFor(Party p) { + DataAssociationCursor dac = ((DataAssociation) get("roles")).cursor(); + if (p instanceof User) { + Filter f = dac.addInSubqueryFilter( + "id", "com.arsdigita.workspace.RolesForUser"); + f.set("participantID", p.getID()); + } else if (p instanceof Group) { + Filter f = dac.addInSubqueryFilter( + "id", "com.arsdigita.workspace.RolesForGroup"); + f.set("participantID", p.getID()); + } else { + throw new IllegalArgumentException( + "received party that was neither user nor group"); + } + return new RoleCollection(dac); + } + + /////Tab Management + + public void addPortalTab(PortalTab ptab) { + add("workspaceTab",ptab); + moveTabToTail(ptab); + } + + public void removePortalTab(PortalTab ptab) { + remove("workspaceTab",ptab); + } + + // Can return null. + public PortalTabCollection getTabsForPortalSite() { + DataAssociation association = (DataAssociation)get("workspaceTab"); + + if (association == null) { + return null; + } + DataAssociationCursor tabsCursor + = association.getDataAssociationCursor(); + tabsCursor.addOrder("sortKey"); + + return new PortalTabCollection(tabsCursor); + } + + public void swapTabWithPrevious(PortalTab ptab) + throws com.arsdigita.persistence.PersistenceException + { + int newKey = ptab.getSortKey() - (SORT_KEY_JUMP + 1); + ptab.setSortKey(newKey); + + ptab.save(); + + normalizeTabSortKeys(); + + } + + public void swapTabWithNext(PortalTab ptab) + throws com.arsdigita.persistence.PersistenceException + { + int newKey = ptab.getSortKey() + (SORT_KEY_JUMP + 1); + + ptab.setSortKey(newKey); + + ptab.save(); + + normalizeTabSortKeys(); + } + + public void moveTabToHead(PortalTab ptab) + { + ptab.setSortKey(Integer.MIN_VALUE); + + ptab.save(); + + normalizeTabSortKeys(); + } + + public void moveTabToTail(PortalTab ptab) + { + ptab.setSortKey(Integer.MAX_VALUE); + + ptab.save(); + + normalizeTabSortKeys(); + } + + public void normalizeTabSortKeys() + { + PortalTab ptab; + + PortalTabCollection wtcoll = getTabsForPortalSite(); + + for (int index = SORT_KEY_JUMP; wtcoll.next(); index += SORT_KEY_JUMP) + { + ptab = wtcoll.getPortalTab(); + + ptab.setSortKey(index); + + ptab.save(); + } + + + } + + // + // Member properties + // + + public boolean isReady() { + return ((Boolean)get("isReady")).booleanValue(); + } + + public void setReady(boolean isReady) { + set("isReady", new Boolean(isReady)); + } + + public boolean isDraft() { + return ((Boolean)get("isDraft")).booleanValue(); + } + + public void setDraft(boolean isDraft) { + set("isDraft", new Boolean(isDraft)); + } + + public boolean isPersonalizable() { + return ((Boolean)get("isPersonalizable")).booleanValue(); + } + + public void setPersonalizable(boolean isPersonalizable) { + set("isPersonalizable", new Boolean(isPersonalizable)); + } + + public boolean isSubPortal() { + return ((Boolean)get("isSubPortal")).booleanValue(); + } + + public void setIsSubPortal(boolean issubportal) { + set("isSubPortal", new Boolean(issubportal)); + } + + public boolean isArchived() { + return ((Boolean)get("isArchived")).booleanValue(); + } + + public void setArchived() { + set("isArchived", Boolean.TRUE); + } + + public void setUnarchived() { + set("isArchived", Boolean.FALSE); + } + + public void setCreationDate( Date cdate) { + set("creationDate",cdate); + } + + public void setCreationDate() { + Calendar rightNow = GregorianCalendar.getInstance(); + Date cdate = rightNow.getTime(); + set("creationDate",cdate); + } + + public Date getCreationDate() { + return (Date)get("creationDate"); + } + + public void setArchiveDate(Date adate) { + set("archiveDate",adate); + } + + public void setArchiveDate() { + Calendar rightNow = GregorianCalendar.getInstance(); + Date adate = rightNow.getTime(); + set("archiveDate",adate); + } + + public Date getArchiveDate() { + return (Date)get("archiveDate"); + } + + public void archive() { + Party p; + + //1 - set archive bit + setArchived(); + + //2 - drop permissions + PartyCollection pc = getParticipants(); + while(pc.next()) { + p = pc.getParty(); + removeParticipant(p); + } + + //3 set archivedate + setArchiveDate(); + + } + + public void archiveRecurse() { + + PortalSite portal; + + archive(); + + PortalSiteCollection psc = getChildPortalSites(); + psc.filterForUnarchived(); + while(psc.next()) { + portal = psc.getPortalSite(); + portal.archiveRecurse(); + } + + } + + public void unarchive() { + this.setUnarchived(); + this.setArchiveDate(); + } + + + /** + * Returns the Mission statement for the Portal + */ + public String getMission() { + return (String)get("mission"); + } + + /** + * Set's the mission statement for a Portal. + */ + public void setMission(String mission) { + set("mission", mission); + } + + /** + * Associates a Theme object with this Portal. + */ + public void setTheme(Theme theme) { + set("theme",theme); + } + + /** + * Returns the Theme object for this Portal + */ + public Theme getTheme() { + DataObject dobj; + + dobj = (DataObject)get("theme"); + + if( dobj == null) + return null; + else + { + Theme theme = new Theme(dobj); + return theme; + } + } + + + + /** + *

    Get a list of all the distinct "initials" of participants in + * a Portal Site.

    + * + *

    A participant's initial is defined as the first letter of + * their family name when the participant is a user (i.e. a + * person), and the first letter of the group name if the + * participant is a group.

    + * + *

    The returned Iterator contains the initials in increasing + * alphabetical order.

    + **/ + public Iterator getParticipantInitials() { + DataQuery query = SessionManager.getSession().retrieveQuery + ("com.arsdigita.workspace.WorkspaceParticipantInitials"); + query.setParameter("workspaceID", getID()); + + LinkedList result = new LinkedList(); + while (query.next()) { + result.add(query.get("initial")); + } + + return result.listIterator(); + } + + public static PortalSite createSubPortal(PortalSite ps, User user) { + String urlfrag = "U-" + user.getID().toString(); + PortalSite psite = createPortalSite(urlfrag,ps.getDisplayName(),ps); + psite.setIsSubPortal(true); + + //Grab collection of tabs for ps + PortalTabCollection ptc = ps.getTabsForPortalSite(); + + //for each, create duplicate tab for new psite + PortalTab ptab; + PortalTab newtab; + String layout; + Portlet portlet; + AgentPortlet aportlet; + SubPortalTab subtab; + PortletCollection portletcollection; + while(ptc.next()) { + ptab = ptc.getPortalTab(); + layout = ptab.getLayout(); + if(layout != null) { + //If tab layout has a lowercase W or N, make that tab a SubPortalTab. + if((layout.indexOf('w') != (-1)) || (layout.indexOf('n') != (-1))) { + //create subtab + portletcollection = ptab.getPortlets(); + for(int i = 0; i < layout.length(); i++) { + if(layout.charAt(i) == 'n' || layout.charAt(i) == 'w') + portletcollection. + addNotEqualsFilter("cellNumber",new Integer(i + 1)); + } + subtab = SubPortalTab.createSubTab(ptab.getTitle(), psite); + subtab.setSuperPortalTab(ptab); + subtab.setLayout(ptab.getLayout()); + while(portletcollection.next()) { + portlet = portletcollection.getPortlet(); + aportlet = AgentPortlet.createAgentPortlet(portlet,subtab,subtab); + subtab.addPortlet(aportlet,portlet.getCellNumber()); + } + subtab.setPortalSite(psite); + subtab.save(); + } else { + //create normal tab + portletcollection = ptab.getPortlets(); + newtab = PortalTab.createTab(ptab.getTitle(), psite); + newtab.setLayout(ptab.getLayout()); + while(portletcollection.next()) { + portlet = portletcollection.getPortlet(); + aportlet = AgentPortlet.createAgentPortlet(portlet,newtab,newtab); + newtab.addPortlet(aportlet,portlet.getCellNumber()); + } + newtab.setPortalSite(psite); + newtab.save(); + } + } + } + psite.save(); + + return psite; + } + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/PortalSiteCollection.java b/ccm-portalserver/src/com/arsdigita/portalserver/PortalSiteCollection.java new file mode 100644 index 000000000..84ff643c5 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/PortalSiteCollection.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + +import com.arsdigita.web.ApplicationCollection; +import com.arsdigita.util.Assert; +import com.arsdigita.persistence.DataCollection; +import java.math.BigDecimal; +import org.apache.log4j.Logger; + +/** + *

    Experimental

    + * + * @author Justin Ross <jross@redhat.com> + * @version $Id: PortalSiteCollection.java pboy $ + */ +public class PortalSiteCollection extends ApplicationCollection { + + private static final Logger s_log = Logger.getLogger + (PortalSiteCollection.class); + + public PortalSiteCollection(DataCollection dataCollection) { + super(dataCollection); + } + + public void filterToPortalSite(BigDecimal id) { + m_dataCollection.addEqualsFilter("id", id); + } + + public void filterForArchived() { + m_dataCollection.addEqualsFilter("isArchived", Boolean.TRUE); + } + + public void filterForUnarchived() { + m_dataCollection.addEqualsFilter("isArchived", Boolean.FALSE); + } + + /** + * Get the current item as a PortalSite domain object. + * + * @return a PortalSite domain object. + * @post return != null + */ + public PortalSite getPortalSite() { + PortalSite portalsite = (PortalSite)getDomainObject(); + + // Assert.assertNotNull(portalsite); + Assert.exists(portalsite); + + return portalsite; + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/PortalSummaryPortlet.java b/ccm-portalserver/src/com/arsdigita/portalserver/PortalSummaryPortlet.java new file mode 100644 index 000000000..b3b7599ab --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/PortalSummaryPortlet.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.persistence.DataObject; +import com.arsdigita.portal.apportlet.AppPortlet; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.ListPanel; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SegmentedPanel; +import com.arsdigita.bebop.portal.AbstractPortletRenderer; +import com.arsdigita.kernel.PartyCollection; +import com.arsdigita.persistence.DataQuery; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.xml.Element; +import com.arsdigita.web.URL; + +/** + * + * @author dennis + * @version "$Id: PortalSummaryPortlet.java pboy $ + */ +public class PortalSummaryPortlet extends AppPortlet { + + public static final String BASE_DATA_OBJECT_TYPE = + "com.arsdigita.workspace.WorkspaceSummaryPortlet"; + + private static final int MAX_PARTICIPANTS_FOR_LISTING = 15; + + @Override + protected String getBaseDataObjectType() { + return BASE_DATA_OBJECT_TYPE; + } + + // Retrieve. + public PortalSummaryPortlet(DataObject dataObject) { + super(dataObject); + } + + @Override + protected AbstractPortletRenderer doGetPortletRenderer() { + return new PortalSummaryPortletRenderer(this); + } + + @Override + public String getZoomURL() { + return URL.getDispatcherPath() + getParentApplication() + .getPrimaryURL() + "participants/"; + } + + /** + * + */ + private static class PortalSummaryPortletRenderer + extends AbstractPortletRenderer { + private PortalSummaryPortlet m_portlet; + + public PortalSummaryPortletRenderer( PortalSummaryPortlet portlet) { + m_portlet = portlet; + } + + protected void generateBodyXML(PageState ps, Element parent) { + PortalSite currentPortal = + (PortalSite)m_portlet.getParentApplication(); + + if (currentPortal == null) { + return; + } + + SegmentedPanel main = new SegmentedPanel(); + + String mission = currentPortal.getMission(); + if (mission != null) { + main.addSegment(new Label(GlobalizationUtil.globalize( + "cw.workspace.mission")), + new Label(mission,false)); + } + + PartyCollection pc = currentPortal.getParticipants(); + ListPanel participants = new ListPanel(ListPanel.UNORDERED); + + long participantCount = pc.size(); + if (participantCount > MAX_PARTICIPANTS_FOR_LISTING) { + DataQuery dq = SessionManager.getSession().retrieveQuery( + "com.arsdigita.workspace.RolesWithCounts"); + dq.setParameter("workspaceID", currentPortal.getID()); + + while (dq.next()) { + participants.add(new Label( + dq.get("roleCount") + " " + dq.get("roleName"))); + } + + participants.add( new Label(participantCount + " " + + " Total participants")); + } else { + while (pc.next()) { + participants.add(new Label(pc.getDisplayName())); + } + } + + Link searchLink = new Link( new Label(GlobalizationUtil + .globalize( + "cw.workspace.search_participants")), + "participants/"); + // deprecated, replaced by setVar in class Link + // searchLink.addURLVars("action", "search"); + searchLink.setVar("action", "search"); + participants.add(searchLink); + + main.addSegment(new Label(GlobalizationUtil + .globalize("cw.workspace.participants")), + participants); + + main.generateXML(ps, parent); + } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/PortalTab.java b/ccm-portalserver/src/com/arsdigita/portalserver/PortalTab.java new file mode 100644 index 000000000..a7b1f0fd3 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/PortalTab.java @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.domain.DomainObject; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.DataCollection; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.persistence.OID; +import com.arsdigita.portal.Portal; +// import com.arsdigita.portal.PortletCollection; +import com.arsdigita.kernel.Resource; +import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.util.Assert; +import java.math.BigDecimal; + +/** + * A PortalTab is a tool organizing content in a Portal. + * A PortalTab includes logic for sorting and displaying portlets + * in a specific layout manner. + * + * @author Jim Parsons + */ +public class PortalTab extends Portal { + + private static final int SORT_KEY_JUMP = 10; + private static final String DEFAULT_LAYOUT = "NW"; + + /** + * The type of the {@link com.arsdigita.persistence.DataObject} + * that stands behind this {@link + * com.arsdigita.domain.DomainObject}. + */ + public static final String BASE_DATA_OBJECT_TYPE = + "com.arsdigita.workspace.WorkspaceTab"; + + @Override + protected String getBaseDataObjectType() { + return BASE_DATA_OBJECT_TYPE; + } + + public PortalTab(DataObject dataObject) { + super(dataObject); + } + + + public static PortalTab createTab(String title, Resource parent) { + PortalTab ptab = + (PortalTab)Portal.create(BASE_DATA_OBJECT_TYPE, title, parent); + ptab.setSortKey(0); + ptab.setLayout(DEFAULT_LAYOUT); + return ptab; + } + + public static PortalTab createTab(String title) { + PortalTab ptab = + (PortalTab)Portal.create(BASE_DATA_OBJECT_TYPE, title, null); + ptab.setSortKey(0); + ptab.setLayout(DEFAULT_LAYOUT); + return ptab; + } + + /** + * Retrieve an existing PortalTab based on a PortalTab ID. + * + * @param portalID the ID of the PortalTab to retrieve. + * @return an existing PortalTab. Note that the return value may be + * null if no PortalTab of this ID exists. + * @pre prtlTabID != null + */ + public static PortalTab retrieveTab(BigDecimal prtlTabID) { + // Assert.assertNotNull(prtlTabID); + Assert.exists(prtlTabID); + + return PortalTab.retrieveTab(new OID(BASE_DATA_OBJECT_TYPE, prtlTabID)); + } + + /** + * Retrieve an existing PortalTab based on a portal_tab data object. + * + * @param dataObject the data object of the PortalTab to retrieve. + * @return an existing PortalTab. Note that the return value may be + * null if no PortalTab data object for this ID exists. + * @pre dataObject != null + */ + public static PortalTab retrieveTab(DataObject dataObject) { + // Assert.assertNotNull(dataObject); + Assert.exists(dataObject); + + DomainObject dobj = DomainObjectFactory.newInstance(dataObject); + return (PortalTab)dobj; + } + + /** + * Retrieve an existing PortalTab based on an OID. + * + * @param oid the OID of the PortalTab to retrieve. + * @pre oid != null + */ + public static PortalTab retrieveTab(OID oid) { + // Assert.assertNotNull(oid); + Assert.exists(oid); + + DataObject dataObject = SessionManager.getSession().retrieve(oid); + + return PortalTab.retrieveTab(dataObject); + } + + public static boolean doesTabExist(BigDecimal bd) { + + OID oid = new OID(BASE_DATA_OBJECT_TYPE, bd); + + DataObject dataObject = SessionManager.getSession().retrieve(oid); + + if (dataObject == null) + return false; + else + return true; + } + + /** + * This is an unusual method that retrieves ALL Portal Tabs... + */ + public static PortalTabCollection retrieveAllTabs() { + DataCollection dataCollection = + SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE); + + PortalTabCollection tabCollection = new PortalTabCollection + (dataCollection); + + return tabCollection; + } + + public static PortalTabCollection getTabsForPortalSite(PortalSite p) { + DataCollection dataCollection = + SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE); + + PortalTabCollection tabCollection = new PortalTabCollection + (dataCollection); + + return tabCollection; + } + + // + // Accessors + // + + /** + * Get the title of this PortalTab. + * + * @return this tab's title. + * @post return != null + */ + @Override + public String getTitle() { + String title = (String)get("title"); + + // Assert.assertNotNull(title); + Assert.exists(title); + + return title; + } + + /** + * Set the title of this PortalTab. + * + * @param title the new title. + * @pre title != null + */ + @Override + public void setTitle(String title) { + // Assert.assertNotNull(title); + Assert.exists(title); + + set("title", title); + } + + public void setPortalSite(PortalSite psite) { + setAssociation("workspace", psite); + } + + public PortalSite getPortalSite() { + + DataObject dataObject = (DataObject) get("workspace"); + + // Assert.assertNotNull(dataObject, "dataObject"); + Assert.exists(dataObject, "dataObject"); + + return new PortalSite(dataObject); + + } + + + /** + * Get the sort key of this PortalTab. The sort key is used + * to order a set of tabs in a particular Portal Site. + * + * @return the portal sort key. + */ + public int getSortKey() { + return ((Integer)get("sortKey")).intValue(); + } + + public void setSortKey(int sortKey) { + set("sortKey", new Integer(sortKey)); + } + + //Layout getter and setter... + + public String getLayout() { + return ((String)get("tab_layout")); + } + + public void setLayout(String layout) { + set("tab_layout", layout); + } + + private boolean m_wasNew; + + @Override + protected void beforeSave() { + m_wasNew = isNew(); + super.beforeSave(); + } + + @Override + public void afterSave() { + super.afterSave(); + + if (m_wasNew) { + PortalSite psite = (PortalSite) DomainObjectFactory.newInstance( + (DataObject) get("workspace")); + PermissionService.setContext(this, psite); + } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/PortalTabCollection.java b/ccm-portalserver/src/com/arsdigita/portalserver/PortalTabCollection.java new file mode 100644 index 000000000..35037d0d2 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/PortalTabCollection.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + +import com.arsdigita.domain.DomainCollection; +import com.arsdigita.domain.DomainObject; +import com.arsdigita.persistence.DataCollection; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.util.Assert; +import java.math.BigDecimal; + + /** + * This class represents the Domain Object Collection for + * PortalTab . + * + * @author Jim Parsons + */ + +public class PortalTabCollection extends DomainCollection { + + protected PortalTabCollection(DataCollection dataCollection) { + super(dataCollection); + } + + /** + * Get the ID for the PortalTab for the current row. + * + * @return the id of this PortalTab. + * @post return != null + */ + public BigDecimal getID() { + BigDecimal id = (BigDecimal)m_dataCollection.get("id"); + + // Assert.assertNotNull(id); + Assert.exists(id); + + return id; + } + + /** + * Get the current item as a domain object. + * + * @return the domain object for the current row. + * @post return != null + */ + public DomainObject getDomainObject() { + DomainObject domainObject = getPortalTab(); + + // Assert.assertNotNull(domainObject); + Assert.exists(domainObject); + + return domainObject; + } + + /** + * Get the current item as a PortalTab domain object. + * + * @return a Portal domain object. + * @post return != null + */ + public PortalTab getPortalTab() { + DataObject dataObject = m_dataCollection.getDataObject(); + + PortalTab portalTab = PortalTab.retrieveTab(dataObject); + + // Assert.assertNotNull(portalTab); + Assert.exists(portalTab); + + return portalTab; + } + + /** + * Get the title for the PortalTab for the current row. + * + * @return the title of this PortalTab. + * @post return != null + */ + public String getTitle() { + String title = (String)m_dataCollection.get("title"); + + // Assert.assertNotNull(title); + Assert.exists(title); + + return title; + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/Role.java b/ccm-portalserver/src/com/arsdigita/portalserver/Role.java new file mode 100644 index 000000000..b8e9b12f1 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/Role.java @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.domain.DataObjectNotFoundException; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.kernel.Group; +import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.OID; +import java.math.BigDecimal; + +import org.apache.log4j.Logger; + +public class Role extends Group { + public static final String versionId = "$Id: //portalserver/dev/src/com/arsdigita/portalserver/Role.java#6 $"; + + public static final String BASE_DATA_OBJECT_TYPE = + "com.arsdigita.workspace.Role"; + public static final String MEMBER_TYPE = "members"; + + private static final Logger s_log = Logger.getLogger(Role.class); + private PortalSite m_portalsite; + + protected String getBaseDataObjectType() { + return BASE_DATA_OBJECT_TYPE; + } + + public Role(DataObject obj) { + super(obj); + } + + public Role(OID oid) throws DataObjectNotFoundException { + super(oid); + } + + public Role(BigDecimal id) throws DataObjectNotFoundException { + super(new OID(BASE_DATA_OBJECT_TYPE, id)); + } + + protected Role(PortalSite psite, String roleName, String assigneeTitle, + String description, boolean isSystem) { + super(BASE_DATA_OBJECT_TYPE); + setPortalSite(psite); + setSystem(isSystem); + setRoleNameInternal(roleName); + setAssigneeTitleInternal(assigneeTitle); + setDescriptionInternal(description); + } + + /** + * Creates a user defined role, as opposed to a system role. + **/ + public static Role createRole(PortalSite psite, String roleName, + String assigneeTitle, String description) { + return createRole(psite, roleName, assigneeTitle, description, false); + } + + /** + * Creates a role in the specified portal. + * + * @param portalsite the portal site in which to create the role + * @param roleName the name of the role to be created + * @param isSystem whether or not the role should be created as a system + * role. + **/ + public static Role createRole(PortalSite psite, String roleName, + String assigneeTitle, String description, + boolean isSystem) { + return new Role(psite, roleName, assigneeTitle, description, isSystem); + } + + public static Role createRole(PortalSite psite, String roleName, + String assigneeTitle, String description, + boolean isSystem, String roleType) { + Role role = new Role(psite, roleName, assigneeTitle, description, isSystem); + + if ( s_log.isDebugEnabled() ) { + s_log.debug("creating role ", new Throwable()); + } + + role.setRoleTypeInternal(roleType); + + return role; + } + + public String getRoleName() { + return (String) get("roleName"); + } + + /** + * Modify the role name. This will also change the group name to + * appropriately reflect the new role name and the workspace title. + * The role name of a system role can not be modified. + * + * @throws RuntimeException when this is a system role + **/ + public void setRoleName(String roleName) { + systemCheck(); + setRoleNameInternal(roleName); + } + + private void setRoleNameInternal(String roleName) { + set("roleName", roleName); + setName(getPortalSite().getTitle() + ": " + roleName); + } + + public String getAssigneeTitle() { + return (String) get("assigneeTitle"); + } + + public void setAssigneeTitle(String title) { + systemCheck(); + setAssigneeTitleInternal(title); + } + + private void setAssigneeTitleInternal(String title) { + set("assigneeTitle", title); + } + + public String getDescription() { + return (String) get("description"); + } + + public void setDescription(String description) { + systemCheck(); + setDescriptionInternal(description); + } + + private void setDescriptionInternal(String description) { + set("description", description); + } + + private void setRoleTypeInternal(String type) { + set("type", type); + } + + public PortalSite getPortalSite() { + if (m_portalsite == null) { + m_portalsite = (PortalSite) + DomainObjectFactory.newInstance((DataObject) get("workspace")); + } + + return m_portalsite; + } + + private void setPortalSite(PortalSite portalsite) { + setAssociation("workspace", portalsite); + m_portalsite = portalsite; + } + + private void setSystem(boolean isSystem) { + set("isSystem", isSystem ? Boolean.TRUE : Boolean.FALSE); + } + + /** + * Returns whether or not this is a system role. A system role can not + * have its name changed, and can not be deleted. + * + * @return whether or not this is a system role + **/ + public boolean isSystem() { + return Boolean.TRUE.equals(get("isSystem")); + } + + private void systemCheck() { + if (isSystem()) { + throw new RuntimeException("Can not modify system roles."); + } + } + + /** + *

    Delete the Role. This method removes all members and + * subgroups of the Role, and revokes all permission grants.

    + **/ + public void delete() { + if (isSystem()) { + throw new RuntimeException("Can't delete system roles"); + } + + clearMembers(); + clearSubgroups(); + PermissionService.revokePartyPermissions(getOID()); + + super.delete(); + } + + protected void afterSave() { + PermissionService.setContext(this, m_portalsite); + super.afterSave(); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/RoleCollection.java b/ccm-portalserver/src/com/arsdigita/portalserver/RoleCollection.java new file mode 100644 index 000000000..3ccc9b1ab --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/RoleCollection.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.kernel.GroupCollection; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.DataCollection; + +public class RoleCollection extends GroupCollection { + + private PortalSite m_portalsite; + + protected RoleCollection(DataCollection dc, PortalSite p) { + super(dc); + m_portalsite = p; + } + + public RoleCollection(DataCollection dc) { + super(dc); + } + + public String getRoleName() { + return (String) m_dataCollection.get("roleName"); + } + + public boolean isSystem() { + return ((Boolean) m_dataCollection.get("isSystem")).booleanValue(); + } + + public PortalSite getPortalSite() { + if (m_portalsite == null) { + return (PortalSite) DomainObjectFactory.newInstance( + (DataObject) m_dataCollection.get("workspace")); + } else { + return m_portalsite; + } + } + + public Role getRole() { + return (Role)getDomainObject(); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/SubPortalTab.java b/ccm-portalserver/src/com/arsdigita/portalserver/SubPortalTab.java new file mode 100644 index 000000000..70930d2de --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/SubPortalTab.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + +//import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.DataQuery; +import com.arsdigita.persistence.DataCollection; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.persistence.Session; +//import com.arsdigita.persistence.OID; +import com.arsdigita.persistence.DataQueryDataCollectionAdapter; +import com.arsdigita.portal.Portal; +import com.arsdigita.portal.PortletCollection; +import com.arsdigita.kernel.Resource; +//import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.util.Assert; + +import java.util.ArrayList; + +/** + * A PortalTab is a tool organizing content in a Portal. + * A PortalTab includes logic for sorting and displaying portlets + * in a specific layout manner. + * + * This Class extends PortalTab and is aware of a another PortalTab + * on the system that it relies on for part of its Portlets. It also + * overrides the getPortlets() method, and the PortletCollection + * returned is a union of its native Portlets plus the Portlets + * that reside in locked tiles in the associated PortalTab. + * + * @author Jim Parsons + */ +public class SubPortalTab extends PortalTab { + + private static final int SORT_KEY_JUMP = 10; + + /** + * The type of the {@link com.arsdigita.persistence.DataObject} that + * stands behind this {@link com.arsdigita.domain.DomainObject}. + */ + public static final String BASE_DATA_OBJECT_TYPE = + "com.arsdigita.workspace.SubWorkspaceTab"; + + @Override + protected String getBaseDataObjectType() { + return BASE_DATA_OBJECT_TYPE; + } + + /** + * Standard Constructor retrieves SubPortalTab from + * @param dataObject + */ + public SubPortalTab(DataObject dataObject) { + super(dataObject); + } + + + /** + * + * @param title + * @param parent + * @return + */ + public static SubPortalTab createSubTab(String title, Resource parent) { + SubPortalTab ptab = + (SubPortalTab)Portal.create(BASE_DATA_OBJECT_TYPE, title, parent); + ptab.setSortKey(0); + return ptab; + } + + public static SubPortalTab createSubTab(String title) { + SubPortalTab ptab = + (SubPortalTab)Portal.create(BASE_DATA_OBJECT_TYPE, title, null); + ptab.setSortKey(0); + return ptab; + } + + @Override + public PortletCollection getPortlets() { + PortalTab ptab = getSuperPortalTab(); + //If the super portal tab that this subportal tab is associated with + //has been deleted, unlock the cells in this tab, + //and then just call super.getPortlets(); + if(ptab == null) { + String thislayout = this.getLayout(); + this.setLayout(thislayout.toUpperCase()); + return super.getPortlets(); + } + + String layout = ptab.getLayout(); + + //This section builds up a list of cell numbers that must be + //rendered from the superportal tab + ArrayList l = new ArrayList(); + char c; + boolean found_one = false; + for(int i=0;i < layout.length();i++) { + c = layout.charAt(i); + if((c == 'n') || (c == 'w')) { + l.add(new Integer(i)); + found_one = true; + } + } + + if(found_one) { //At least one cell region was found to be locked + Session session = SessionManager.getSession(); + DataQuery query = + session.retrieveQuery("com.arsdigita.workspace.getSubPortalPortlets"); + query.setParameter("subPortalTabID", this.getID()); + query.setParameter("cells", l); + DataCollection dc = + new DataQueryDataCollectionAdapter(query,"portlet"); + PortletCollection pc = new PortletCollection(dc); + return pc; + } else { //this case means the super tab still exists, but no longer + //has locked regions. + return super.getPortlets(); + } + } + + + public void setSuperPortalTab(PortalTab ptab) { + setAssociation("workspaceTab", ptab); + } + + public PortalTab getSuperPortalTab() { + DataObject dataObject = (DataObject) get("workspaceTab"); + + // Assert.assertNotNull(dataObject, "dataObject"); + Assert.exists(dataObject, "dataObject"); + + return new PortalTab(dataObject); + } + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/Theme.java b/ccm-portalserver/src/com/arsdigita/portalserver/Theme.java new file mode 100644 index 000000000..d6b005e33 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/Theme.java @@ -0,0 +1,484 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + +import com.arsdigita.kernel.ACSObject; +// import com.arsdigita.kernel.Kernel; +// import com.arsdigita.kernel.Party; +// import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.persistence.DataCollection; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.OID; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.util.Assert; + +import java.math.BigDecimal; + +/** + * A theme. + * - + * A theme is a collection of color choices and (possibly) images + * that style a Portal. A theme is inherently tied to to the + * underlying design of the portal page; for example, a theme that + * stores and sets a color for a context bar is only useful if the + * design of the Portal that uses such a theme has, in fact, a context + * bar. + *

    + * A particular portal design/layout is made up of components + * such as context bar, colored horizontal rules, tabbed panes...etc. which + * we refer to as a skin. A skin can have a theme applied to it, which + * renders components with desired colors, fonts, and background images. This + * Theme class is for enhancing the default skin that ships with Portal Server. + *

    + * If a developer desires to create their own Portal design or skin, then + * the following files would be need to be implemented: + *

      + *
    • A PDL file describing the data model for the skin's thematic elements.
    • + *
    • A class like this one that implements Themes, with getter/setters for + * thematic elements
    • + *
    • A CSS sheet with class names that correspond to the class names that + * the buildStyleBlock() method uses (see below)
    • + *
    • Appropriate XSL sheet that utilizes the CSS class names.
    + *

    + * This class provides setters and getters for all of the elements in the + * default Portal Server skin, plus a method that builds a block of CSS tags + * that are inserted into the output stream and used to override default + * choices for the default skin. + * + * + * + * @author Jim Parsons + * + */ + +public class Theme extends ACSObject implements Themes { + + + /** + * The type of the {@link com.arsdigita.persistence.DataObject} + * that stands behind this {@link + * com.arsdigita.domain.DomainObject}. + */ + public static final String BASE_DATA_OBJECT_TYPE = + "com.arsdigita.workspace.Theme"; + + @Override + protected String getBaseDataObjectType() { + return BASE_DATA_OBJECT_TYPE; + } + + public Theme(DataObject dataObject) { + super(dataObject); + } + + public Theme(String name) { + super(BASE_DATA_OBJECT_TYPE); + setName(name); + setContextBarColor("#006600"); + setContextBarColor("#000000"); + setActiveTabColor("#550000"); + setInactiveTabColor("#000055"); + setActiveTabTextColor("#000000"); + setInactiveTabTextColor("#000000"); + setTopRuleColor("#770033"); + setBottomRuleColor("#770033"); + setPortletHeaderColor("#440500"); + setPortletIconColor("#440500"); + setPortletBorderColor("#000048"); + setPortletBorderStyle("solid"); + setPortletHeaderTextColor("#000000"); + setPageBGColor("#ffffff"); + setPageBGImage(""); + setNarrowBGColor("#ffffff"); + setBodyTextColor("#000000"); + } + + + /** + * Retrieve an existing Theme based on an ID. + * + */ + public static Theme retrieveTheme(BigDecimal themeID) { + // Assert.assertNotNull(themeID); + Assert.exists(themeID); + + return Theme.retrieveTheme(new OID(BASE_DATA_OBJECT_TYPE, themeID)); + } + + /** + * Retrieve an existing Theme based on a data object. + * + * @param dataObject the data object of the Theme to retrieve. + * @return an existing Theme. Note that the return value may be + * null if no Theme data object for this ID exists. + * @pre dataObject != null + */ + public static Theme retrieveTheme(DataObject dataObject) { + // Assert.assertNotNull(dataObject); + Assert.exists(dataObject); + + return new Theme(dataObject); + } + + /** + * Retrieve an existing Theme based on an OID. + * + * @param oid the OID of the Theme to retrieve. + * @pre oid != null + */ + public static Theme retrieveTheme(OID oid) { + // Assert.assertNotNull(oid); + Assert.exists(oid); + + DataObject dataObject = SessionManager.getSession().retrieve(oid); + + return Theme.retrieveTheme(dataObject); + } + + + public static ThemeCollection retrieveAllThemes() { + DataCollection dataCollection = + SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE); + + ThemeCollection themeCollection = new ThemeCollection + (dataCollection); + + return themeCollection; + } + + // + // Accessors + // + + /** + * Get the title of this Theme. + * + * @return this Themes title. + */ + public String getName() { + String name = (String)get("theme_name"); + + // Assert.assertNotNull(name); + Assert.exists(name); + + return name; + } + + /** + * Set the title of this Theme. + * + */ + public void setName(String name) { + // Assert.assertNotNull(name); + Assert.exists(name); + + set("theme_name", name); + } + + /** + * Get the Description of this Theme. + * + */ + public String getDescription() { + String description = (String)get("theme_desc"); + + // Assert.assertNotNull(description); + Assert.exists(description); + + return description; + } + + /** + * Set the description for this Theme. + * + */ + public void setDescription(String desc) { + //Assert.assertNotNull(desc); + + set("theme_desc",desc); + } + + + public void setContextBarColor(String color) { + set("ctx_bar_color", color); + } + + public String getContextBarColor() { + String cbc = (String)get("ctx_bar_color"); + + return cbc; + } + + public void setContextBarTextColor(String color) { + set("ctx_bar_text_color", color); + } + + public String getContextBarTextColor() { + String cbtc = (String)get("ctx_bar_text_color"); + + return cbtc; + } + + public void setActiveTabColor(String color) { + set("active_tab_color",color); + } + + public String getActiveTabColor() { + String atc = (String)get("active_tab_color"); + + return atc; + } + + + public void setInactiveTabColor(String color) { + set("inactive_tab_color",color); + } + + public String getInactiveTabColor() { + String itc = (String)get("inactive_tab_color"); + + return itc; + } + + + public void setActiveTabTextColor(String color) { + set("active_tab_text_color",color); + } + + public String getActiveTabTextColor() { + String attc = (String)get("active_tab_text_color"); + + return attc; + } + + + public void setInactiveTabTextColor(String color) { + set("inactive_tab_text_color",color); + } + + public String getInactiveTabTextColor() { + String ittc = (String)get("inactive_tab_text_color"); + + return ittc; + } + + + public void setTopRuleColor(String color) { + set("top_rule",color); + } + + public String getTopRuleColor() { + String trc = (String)get("top_rule"); + + return trc; + } + + + public void setBottomRuleColor(String color) { + set("bottom_rule",color); + } + + public String getBottomRuleColor() { + String brc = (String)get("bottom_rule"); + + return brc; + } + + + public void setPortletHeaderColor(String color) { + set("portlet_head",color); + } + + public String getPortletHeaderColor() { + String phc = (String)get("portlet_head"); + + return phc; + } + + + public void setPortletIconColor(String color) { + set("portlet_icon",color); + } + + public String getPortletIconColor() { + String pic = (String)get("portlet_icon"); + + return pic; + } + + + public void setPortletBorderColor(String color) { + set("portlet_border_color",color); + } + + public String getPortletBorderColor() { + String pbc = (String)get("portlet_border_color"); + + return pbc; + } + + + public void setPortletBorderStyle(String style) { + set("portlet_border_style",style); + } + + public String getPortletBorderStyle() { + String pbs = (String)get("portlet_border_style"); + + return pbs; + } + + + public void setPortletHeaderTextColor(String color) { + set("portlet_header_text_color",color); + } + + public String getPortletHeaderTextColor() { + String phtc = (String)get("portlet_header_text_color"); + + return phtc; + } + + + public void setPageBGColor(String color) { + set("page_bg_color",color); + } + + public String getPageBGColor() { + String pbgc = (String)get("page_bg_color"); + + return pbgc; + } + + + public void setPageBGImage(String url) { + set("page_bg_image",url); + } + + public String getPageBGImage() { + String pbgi = (String)get("page_bg_image"); + + return pbgi; + } + + + public void setNarrowBGColor(String color) { + set("narrow_bg_color",color); + } + + public String getNarrowBGColor() { + String nbc = (String)get("narrow_bg_color"); + + return nbc; + } + + + public void setBodyTextColor(String color) { + set("body_text_color",color); + } + + public String getBodyTextColor() { + String btc = (String)get("body_text_color"); + + return btc; + } + + + @Override + protected void afterSave() { + super.afterSave(); + } + + public StringBuffer buildStyleBlock() { + + StringBuffer buffer = new StringBuffer(); + + buffer.append(""); + + return (buffer); + + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ThemeCollection.java b/ccm-portalserver/src/com/arsdigita/portalserver/ThemeCollection.java new file mode 100644 index 000000000..3bcc92c1b --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ThemeCollection.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + +import com.arsdigita.domain.DomainCollection; +import com.arsdigita.domain.DomainObject; +import com.arsdigita.persistence.DataCollection; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.util.Assert; +import java.math.BigDecimal; + +public class ThemeCollection extends DomainCollection { + + protected ThemeCollection(DataCollection dataCollection) { + super(dataCollection); + } + + /** + * Get the ID for the Theme for the current row. + * + * @return the id of this Theme. + * @post return != null + */ + public BigDecimal getID() { + BigDecimal id = (BigDecimal)m_dataCollection.get("id"); + + // Assert.assertNotNull(id); + Assert.exists(id); + + return id; + } + + /** + * Get the current item as a domain object. + * + * @return the domain object for the current row. + * @post return != null + */ + public DomainObject getDomainObject() { + DomainObject domainObject = getTheme(); + + // Assert.assertNotNull(domainObject); + Assert.exists(domainObject); + + return domainObject; + } + + /** + * Get the current item as a Theme domain object. + * + * @return a Theme domain object. + * @post return != null + */ + public Theme getTheme() { + DataObject dataObject = m_dataCollection.getDataObject(); + + Theme theme = Theme.retrieveTheme(dataObject); + + // Assert.assertNotNull(theme); + Assert.exists(theme); + + return theme; + } + + /** + * Get the name for the Theme for the current row. + * + * @return the name of this theme. + * @post return != null + */ + public String getName() { + String name = (String)m_dataCollection.get("theme_name"); + + // Assert.assertNotNull(name); + Assert.exists(name); + + return name; + } + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/Themes.java b/ccm-portalserver/src/com/arsdigita/portalserver/Themes.java new file mode 100644 index 000000000..dd2fa6457 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/Themes.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + + +/** + * This interface describes the functionality common to + * Theme objects. + * + * @author Jim Parsons + */ + +public interface Themes { + + /** + * Generates a stringbuffer describing the parameters for the + * implementing Theme Object. See the documentation at {@link Theme} + * for an explanation of building and using Themes. + */ + StringBuffer buildStyleBlock(); + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ToolPage.java b/ccm-portalserver/src/com/arsdigita/portalserver/ToolPage.java new file mode 100644 index 000000000..3b79c59a5 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ToolPage.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.bebop.Container; +import com.arsdigita.bebop.DimensionalNavbar; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.event.PrintEvent; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.web.Application; +import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.permissions.PermissionDescriptor; +import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; +import com.arsdigita.portalserver.personal.PersonalPortal; +import com.arsdigita.util.Assert; +import org.apache.log4j.Logger; + +/** + *

    ToolPage class

    + * + *

    This is a common page to be used by all applications for + * consistent styling.

    + * + * @author Tracy Adams + * @version $Revision: #5 $ $Date: 2004/08/17 $ + * @version $Id: ToolPage.java pboy $ + */ + +/* XXX Have to control links with permissions and + * add access control + */ +public class ToolPage extends PortalPage { + + private static final Logger s_log = Logger.getLogger(ToolPage.class); + + /* + * There are 2 views: user and admin. + * m_view determines which context bar and + * view link to show. + */ + private String m_view; + + private Link m_viewLink; + + public ToolPage() { + this(null); + } + + /** + * @param view A String that specifies which application view to + * show. Valid values: "user", "admin" and "null". If view is + * "null", there will be no right-hand navigation link. Note - + * We've decided not to have the right-hand navigation link at + * all. Instead, you should create tabs. So, once the + * applications are migrated, view will always be null and we can + * remove view altogether. + */ + public ToolPage(String view) { + super(); + + m_view = view; + } + + @Override + protected void buildContextBar() { + DimensionalNavbar navbar = new DimensionalNavbar(); + + navbar.setClassAttr("portalNavbar"); + + navbar.add(new LoggedInLinkWrapper(new PersonalPortalLinkPrinter())); + + // This link will not show up if the current workspace is a + // personal portal. + Link current = new Link(new CurrentPortalLinkPrinter()) { + @Override + public boolean isVisible(PageState state) { + PortalSite psite = PortalSite.getCurrentPortalSite + (state.getRequest()); + + return !(psite instanceof PersonalPortal); + } + }; + navbar.add(current); + + if (m_view != null && m_view.equals("admin")) { + navbar.add(new Link(new CurrentApplicationLinkPrinter()) { + @Override + public boolean isVisible(PageState ps) { + return userIsAdmin(ps); + }}); + navbar.add(new Label(GlobalizationUtil.globalize( + "cw.workspace.administration")) { + @Override + public boolean isVisible(PageState ps) { + return userIsAdmin(ps); + }}); + } else { + navbar.add(new Label(new CurrentApplicationLabelPrinter())); + } + + getHeader().add(navbar); + } + + @Override + protected void buildTitle() { + class ApplicationAdminLabelPrinter implements PrintListener { + public void prepare(PrintEvent e) { + Label targetLabel = (Label)e.getTarget(); + PageState pageState = e.getPageState(); + + Application application = Application.getCurrentApplication + (pageState.getRequest()); + + // Assert.assertNotNull(application, "application"); + Assert.exists(application, "application"); + + targetLabel.setLabel + (application.getTitle() + " Administration"); + } + } + + if (m_view != null && m_view.equals("admin")) { + setTitle(new Label(new ApplicationAdminLabelPrinter())); + } else { + setTitle(new Label(new CurrentApplicationLabelPrinter())); + } + } + + @Override + protected void buildHeader(Container header) { + if (m_view != null) { + if (m_view.equals("user")) { + m_viewLink = new Link + ("Administration view", "./admin/index.jsp") { + @Override + public boolean isVisible(PageState ps) { + return userIsAdmin(ps); + }}; + } else if (m_view.equals("admin")) { + m_viewLink = new Link( new Label(GlobalizationUtil.globalize( + "cw.workspace.user_view")), "../index.jsp"); + } + } + + if (m_viewLink != null) { + m_viewLink.setClassAttr("portalControl"); + + header.add(m_viewLink); + } + } + + private boolean userIsAdmin(PageState ps) { + PermissionDescriptor permDescriptor = + new PermissionDescriptor(PrivilegeDescriptor.ADMIN, + Application.getCurrentApplication(ps.getRequest()), + Kernel.getContext().getParty()); + return PermissionService.checkPermission(permDescriptor); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/Util.java b/ccm-portalserver/src/com/arsdigita/portalserver/Util.java new file mode 100644 index 000000000..eb434323c --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/Util.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver; + +import com.arsdigita.bebop.PageState; +// import com.arsdigita.web.Web; +import com.arsdigita.web.LoginSignal; +// import com.arsdigita.web.URL; +// import com.arsdigita.web.ParameterMap; +// import com.arsdigita.ui.login.LoginHelper; + +// import javax.servlet.http.HttpServletRequest; +// import java.util.Map; + +public class Util { + public static void redirectToLoginPage(PageState ps) { + throw new LoginSignal(ps.getRequest()); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/admin/Initializer.java b/ccm-portalserver/src/com/arsdigita/portalserver/admin/Initializer.java new file mode 100644 index 000000000..2cadc204e --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/admin/Initializer.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.admin; + +import com.arsdigita.initializer.Configuration; +import org.apache.log4j.Logger; + +import com.arsdigita.persistence.*; +import com.arsdigita.domain.*; +import com.arsdigita.kernel.*; +import com.arsdigita.portalserver.*; +import com.arsdigita.web.*; + +/** + * Initializer + * + * @author rhs@mit.edu + * @version $Revision: #9 $ $Date: 2004/08/17 $ + **/ + +public class Initializer implements com.arsdigita.initializer.Initializer { + + public final static String versionId = "$Id: //portalserver/dev/src/com/arsdigita/portalserver/admin/Initializer.java#9 $ by $Author: dennis $, $DateTime: 2004/08/17 23:19:25 $"; + + private static Logger s_log = Logger.getLogger(Initializer.class); + + private Configuration m_conf = new Configuration(); + + public Configuration getConfiguration() { + return m_conf; + } + + public void startup() { + s_log.info("Initializing PortalServer Admin..."); + + TransactionContext txn = + SessionManager.getSession().getTransactionContext(); + + txn.beginTxn(); + + ApplicationSetup setup = new ApplicationSetup(s_log); + + setup.setApplicationObjectType(PSAdmin.BASE_DATA_OBJECT_TYPE); + setup.setTitle("Portal Server Site Administration"); + setup.setDescription("Displays common administration tasks."); + setup.setPortalApplication(false); + setup.setKey("portal-admin"); + // db based stylesheets no longer used. + // setup.setStylesheet("/packages/portalserver/xsl/portalserver.xsl"); + setup.setDispatcherClass("com.arsdigita.portalserver.admin.ui.Dispatcher"); + setup.setInstantiator(new ACSObjectInstantiator() { + protected DomainObject doNewInstance(DataObject dataObject) { + return new PSAdmin(dataObject); + } + }); + setupAdminInstance(setup.run()); + + txn.commitTxn(); + + s_log.info("Done initializing PortalServer Admin."); + } + + private void setupAdminInstance(final ApplicationType type) { + + if (!Application.isInstalled(PSAdmin.BASE_DATA_OBJECT_TYPE, + "/portal-admin/")) { + s_log.info("There is no Portal Admin application instance on " + + "/portal-admin/. Installing now."); + + KernelExcursion ex = new KernelExcursion() { + protected void excurse() { + setParty(Kernel.getSystemParty()); + Application app = Application.createApplication + (type, "portal-admin", "Site Administration", null); + + app.save(); + } + }; + ex.run(); + + s_log.info("Done installing Portal Admin on /portal-admin/."); + } + } + + public void shutdown() { + // Do nothing. + } + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/admin/PSAdmin.java b/ccm-portalserver/src/com/arsdigita/portalserver/admin/PSAdmin.java new file mode 100644 index 000000000..3c6473de2 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/admin/PSAdmin.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.admin; + +// import com.arsdigita.portalserver.*; +import com.arsdigita.web.Application; +import com.arsdigita.persistence.*; +import org.apache.log4j.Logger; + +/** + * PSAdmin + * - + * This class is a mountable application for general Portalserver + * Administration tasks. It is initialized as /portal-admin, + * and its UI component is com.arsdigita.portalserver.admin.ui.AdminPage.java + * + * @author rhs@mit.edu + * @version $Revision: #4 $ $Date: 2004/08/17 $ + * @version Id: PSAdmin.java pboy $ + */ +public class PSAdmin extends Application { + + private static final Logger s_log = Logger.getLogger(PSAdmin.class); + + public static final String BASE_DATA_OBJECT_TYPE = + "com.arsdigita.admin.CWAdmin"; + + @Override + protected String getBaseDataObjectType() { + return BASE_DATA_OBJECT_TYPE; + } + + public PSAdmin(DataObject dataObject) { + super(dataObject); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/admin/ui/AdminPage.java b/ccm-portalserver/src/com/arsdigita/portalserver/admin/ui/AdminPage.java new file mode 100644 index 000000000..00a7123ff --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/admin/ui/AdminPage.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.admin.ui; + +import com.arsdigita.web.Application; +import com.arsdigita.web.ApplicationCollection; +import com.arsdigita.bebop.table.*; +import com.arsdigita.bebop.*; +import com.arsdigita.dispatcher.*; +import com.arsdigita.portalserver.*; +import com.arsdigita.portalserver.PortalPage; +import com.arsdigita.toolbox.ui.*; +import org.apache.log4j.Logger; + +import com.arsdigita.xml.Document; +import com.arsdigita.xml.Element; + +/** + * AdminPage + * - + * This class is the UI component for Portal-admin. + * + * @author rhs@mit.edu + * @version $Revision: #8 $ $Date: 2004/08/17 $ + */ +class AdminPage extends PortalPage { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/admin/ui/AdminPage.java#8 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + BoxPanel m_bpanel; + + private static Logger s_log = Logger.getLogger + (AdminPage.class.getName()); + + private RequestLocal m_children = new RequestLocal() { + public Object initialValue(PageState ps) { + Application app = Application.getCurrentApplication + (DispatcherHelper.getRequest()); + return app.getChildApplications(); + } + }; + + public AdminPage() { + getHeader().setIdAttr("admin"); + } + + protected void buildContextBar() { + DimensionalNavbar navbar = new DimensionalNavbar(); + + navbar.setClassAttr("portalNavbar"); + + navbar.add(new Link(new PersonalPortalLinkPrinter())); + + navbar.add(new Label(new CurrentApplicationLabelPrinter())); + + getHeader().add(navbar); + } + + /** + * This method outputs a list of links to admin functionality. + */ + + protected void buildBody(Container body) { + + m_bpanel = new BoxPanel(); + m_bpanel.setClassAttr("portaladminapps"); + body.add(m_bpanel); + Link portalCreateLink = new Link("Create Top-Level Portals", + "/portal-admin/portal-create"); + Link portalSiteMapLink = new Link("Manage Portals", + "/portal-admin/portal-sitemap"); + Link managePeopleLink = new Link("Manage Users and Groups", + "/admin"); + m_bpanel.add(portalCreateLink); + m_bpanel.add(portalSiteMapLink); + m_bpanel.add(managePeopleLink); + } + + /** + * This method is called by the generateXML() method of the parent + * class, and writes a CSS style block into the output. + */ + + public void addStyleBlock(PageState state, Document parent) { + PortalSite psite = PortalSite.getCurrentPortalSite(state.getRequest()); + + StringBuffer buffer = new StringBuffer(); + + buffer.append(""); + + Element rootElement = parent.getRootElement(); + + Element styleBlock = rootElement.newChildElement( + "portalserver:styleblock", + "http://www.redhat.com/portalserver/1.0"); + + styleBlock.setCDATASection(buffer.toString()); + + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/admin/ui/Dispatcher.java b/ccm-portalserver/src/com/arsdigita/portalserver/admin/ui/Dispatcher.java new file mode 100644 index 000000000..dad70fd01 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/admin/ui/Dispatcher.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.admin.ui; + +// import com.arsdigita.bebop.*; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.page.BebopMapDispatcher; +import java.util.*; + +/** + * Dispatcher + * + * @author rhs@mit.edu + * @version $Revision: #3 $ $Date: 2004/08/17 $ + **/ + +public class Dispatcher extends BebopMapDispatcher { + + public final static String versionId = "$Id: //portalserver/dev/src/com/arsdigita/portalserver/admin/ui/Dispatcher.java#3 $ by $Author: dennis $, $DateTime: 2004/08/17 23:19:25 $"; + + public Dispatcher() { + Map m = new HashMap(); + Page index = new AdminPage(); + index.lock(); + m.put("", index); + m.put("index.jsp", index); + m.put("index.html", index); + setMap(m); + } + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/enterprise.init b/ccm-portalserver/src/com/arsdigita/portalserver/enterprise.init new file mode 100644 index 000000000..3b4bd33d3 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/enterprise.init @@ -0,0 +1,15 @@ +// Red Hat Enterprise Portal Server initialization file +// +// When running Portal Server, the parameters for +// com.arsdigita.kernel.Initializer must be modified. +// +// ::login-stylesheet:: -> login_ps_en.xsl +// ::subsite-dispatcher-class:: -> com.arsdigita.portalserver.pslogin.PSSubsiteDispatcher + +init com.arsdigita.portalserver.OldInitializer { } + +init com.arsdigita.portalserver.admin.Initializer { } + +init com.arsdigita.portalserver.ui.admin.Initializer { } + +init com.arsdigita.portalserver.personal.Initializer { } diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/permissions/AddGrantForm.java b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/AddGrantForm.java new file mode 100644 index 000000000..6b53f7c80 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/AddGrantForm.java @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.permissions; + + +import java.math.BigDecimal; + +import com.arsdigita.persistence.*; +import com.arsdigita.kernel.*; +import com.arsdigita.kernel.permissions.*; +import com.arsdigita.domain.*; +import com.arsdigita.bebop.*; +import com.arsdigita.bebop.parameters.*; +import com.arsdigita.bebop.event.*; +import org.apache.log4j.Logger; + + + + +class AddGrantForm extends Form { + + // Select value used to indicate 'all types' in situations + // where type-specific grants are possible + final static String ALL_TYPES = "ALL_TYPES"; + + private BigDecimalParameter m_objectParameter; + private BigDecimalParameter m_partyParameter; + private StringParameter m_privilegeParameter; + private StringParameter m_typeParameter; + private RequestLocal m_errorMessageRL; + + private RequestLocal m_grantPermissionRL; + private static final Logger s_log = Logger.getLogger(AddGrantForm.class); + + BigDecimalParameter getObjectParameter() { + return m_objectParameter; + } + + BigDecimalParameter getPartyParameter() { + return m_partyParameter; + } + + StringParameter getPrivilegeParameter() { + return m_privilegeParameter; + } + + StringParameter getTypeParameter() { + return m_typeParameter; + } + + + AddGrantForm(String name, + Container container, + RequestLocal errorMessageRL) { + super(name, container); + setRedirecting(true); + + // These make sure that fireValidate and fireProcess get + // called even when no validation or process listeners are + // added + forwardValidation(); + forwardProcess(); + + m_objectParameter = new BigDecimalParameter("objectID"); + m_partyParameter = new BigDecimalParameter("partyID"); + m_privilegeParameter = new StringParameter("privName"); + m_typeParameter = new StringParameter("typeName"); + m_errorMessageRL = errorMessageRL; + + m_grantPermissionRL = new RequestLocal(); + } + + + protected void fireValidate(FormSectionEvent ev) { + s_log.debug("AddGrantForm.fireValidate running"); + + PageState ps = ev.getPageState(); + + // Retrieve parameter values + FormData fd = ev.getFormData(); + BigDecimal objectID = + (BigDecimal)fd.get(m_objectParameter.getName()); + BigDecimal partyID = + (BigDecimal)fd.get(m_partyParameter.getName()); + String typeName = + (String)fd.get(m_typeParameter.getName()); + String privName = + (String)fd.get(m_privilegeParameter.getName()); + + // Get the OIDs we need for dealing with permissions + OID partyOID = + new OID(Party.BASE_DATA_OBJECT_TYPE, partyID); + OID objectOID = + new OID(ACSObject.BASE_DATA_OBJECT_TYPE, objectID); + + // Determine what privileges we care about + PrivilegeDescriptor testPriv = Grant.s_interestingPrivileges[0]; + + PrivilegeDescriptor newPriv = + PrivilegeDescriptor.get(privName); + + PermissionDescriptor testPerm = + new PermissionDescriptor(testPriv, objectOID, partyOID); + + if (PermissionService.checkDirectPermission(testPerm)) { + String partyName; + try { + Party party = (Party) + DomainObjectFactory.newInstance(partyOID); + partyName = party.getName(); + } catch (DataObjectNotFoundException ex) { + throw new IllegalStateException("Bad Party"); + } + + String objectName; + try { + ACSObject object = (ACSObject) + DomainObjectFactory.newInstance(objectOID); + objectName = object.getDisplayName(); + } catch (DataObjectNotFoundException ex) { + throw new IllegalStateException("Bad Object"); + } + + String errMsg; + if (typeName == null) { + errMsg = + "\"" + partyName + "\"" + " already has a defined right " + + "on \"" + objectName + "\"."; + } else if (typeName.equals(ALL_TYPES)) { + errMsg = + "\"" + partyName + "\" already has a defined right on \"" + + objectName + "\" and its contents."; + } else { + // FIXME: get type plural pretty name and use + // it instead of typeName in this message. + errMsg = + "\"" + partyName + "\" already has a defined right on " + + "the " + typeName + "s contained in \"" + objectName + + "\"."; + } + m_errorMessageRL.set(ps, errMsg); + fd.addError(errMsg); + } else { + PermissionDescriptor perm = + new PermissionDescriptor(newPriv, objectOID, partyOID); + m_grantPermissionRL.set(ps, perm); + } + + if (s_log.isDebugEnabled()) { + if (fd.isValid()) { + s_log.debug("VALID"); + } else { + s_log.debug("INVALID"); + } + + } + + + super.fireValidate(ev); + } + + + protected void fireProcess(FormSectionEvent ev) + throws FormProcessException { + + PermissionDescriptor perm = + (PermissionDescriptor)m_grantPermissionRL.get(ev.getPageState()); + PermissionService.grantPermission(perm); + + // copy logic in GrantsTable + PrivilegeDescriptor pd = perm.getPrivilegeDescriptor(); + if (pd.equals(PrivilegeDescriptor.EDIT) + || pd.equals(PrivilegeDescriptor.ADMIN)) { + PermissionService.grantPermission + (new PermissionDescriptor + (PrivilegeDescriptor.CREATE, + perm.getACSObjectOID(), + perm.getPartyOID())); + } + + super.fireProcess(ev); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/permissions/ErrorMessageDisplay.java b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/ErrorMessageDisplay.java new file mode 100644 index 000000000..c498e2010 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/ErrorMessageDisplay.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.permissions; + +import com.arsdigita.bebop.*; +import com.arsdigita.bebop.event.*; +import com.arsdigita.bebop.util.Color; + +class ErrorMessageDisplay extends Label { + public ErrorMessageDisplay(final RequestLocal errorMessageRL) { + setColor(Color.red); + setClassAttr("pageErrorDisplay"); + addPrintListener(new PrintListener() { + public void prepare(PrintEvent ev) { + Label target = (Label)ev.getTarget(); + String errMsg = + (String)errorMessageRL.get(ev.getPageState()); + if (errMsg != null) { + target.setLabel(errMsg); + } + } + }); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/permissions/Grant.java b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/Grant.java new file mode 100644 index 000000000..754a1f6f3 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/Grant.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.permissions; + +import java.math.BigDecimal; + +import com.arsdigita.persistence.metadata.MetadataRoot; +import com.arsdigita.persistence.metadata.ObjectType; + +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; + +import org.apache.log4j.Logger; + +class Grant { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/permissions/Grant.java#5 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static Logger s_log = Logger.getLogger(Grant.class.getName()); + + static final PrivilegeDescriptor[] s_interestingPrivileges = { + PrivilegeDescriptor.READ, + PrivilegeDescriptor.EDIT, + PrivilegeDescriptor.ADMIN + }; + + // Create is implicit; s_interestingPrivileges is used for display + // while s_privileges is not. + static final PrivilegeDescriptor[] s_privileges = { + PrivilegeDescriptor.READ, + PrivilegeDescriptor.EDIT, + PrivilegeDescriptor.ADMIN, + PrivilegeDescriptor.CREATE + }; + + static final String[] s_privilegePrettyNames = { + "Read", "Edit", "Manage" + }; + + static final int CREATE = 3; + static final int ADMIN = 2; + static final int EDIT = 1; + static final int READ = 0; + + static int getPrivilegeLevel(PrivilegeDescriptor priv) { + if (PrivilegeDescriptor.EDIT.equals(priv)) { + return 1; + } else if (PrivilegeDescriptor.ADMIN.equals(priv)) { + return 2; + } else if (PrivilegeDescriptor.READ.equals(priv)) { + return 0; + } else if (PrivilegeDescriptor.CREATE.equals(priv)) { + return 3; + } + return -1; + } + + public BigDecimal granteeID; + public String granteeName; + public boolean granteeIsUser; + public BigDecimal objectID; + public String objectName; + public PrivilegeDescriptor basePrivilege; + public ObjectType objectType = null; + public String objectTypeDisplayName = null; + public int level; + + public int hashCode() { + if (objectType == null) { + return granteeID.hashCode() + objectID.hashCode(); + } + + return granteeID.hashCode() + + objectID.hashCode() + + objectType.hashCode(); + } + + public boolean equals(Object other) { + if (other == null) { + return false; + } + + if (!(other instanceof Grant)) { + return false; + } + + Grant otherGrant = (Grant) other; + + if (!granteeID.equals(otherGrant.granteeID)) { + return false; + } + + if (!objectID.equals(otherGrant.objectID)) { + return false; + } + + if (objectType == null && otherGrant.objectType == null) { + return true; + } + + if (objectType == null || otherGrant.objectType == null) { + return false; + } + + return objectType.equals(otherGrant.objectType); + } + + public String toString() { + return marshal(granteeID, objectID, basePrivilege, objectType); + } + + void populatePrivilege(PrivilegeDescriptor priv) { + basePrivilege = priv; + level = getPrivilegeLevel(priv); + objectTypeDisplayName = "All Types"; + } + + static Grant unmarshal(String encoded) { + Grant result = new Grant(); + int dot1 = encoded.indexOf('.'); + int dot2 = encoded.indexOf('.', dot1 + 1); + int dot3 = encoded.indexOf('.', dot2 + 1); + + result.granteeID = new BigDecimal(encoded.substring(0, dot1)); + result.objectID = new BigDecimal(encoded.substring(dot1 + 1, dot2)); + result.basePrivilege = + PrivilegeDescriptor.get(encoded.substring(dot2 + 1, dot3)); + result.level = getPrivilegeLevel(result.basePrivilege); + + if (dot3 + 1 < encoded.length()) { + String objectTypeName = encoded.substring(dot3 + 1); + result.objectType = + MetadataRoot.getMetadataRoot().getObjectType(objectTypeName); + } + + return result; + } + + private static String marshal(BigDecimal granteeID, + BigDecimal objectID, + PrivilegeDescriptor privilege, + ObjectType objectType) { + if (objectType != null) { + return granteeID + "." + + objectID + "." + + privilege.getName() + "." + + objectType.getQualifiedName(); + } else { + return granteeID + "." + + objectID + "." + + privilege.getName() + "."; + } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/permissions/GrantsTable.java b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/GrantsTable.java new file mode 100644 index 000000000..9f0f36b06 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/GrantsTable.java @@ -0,0 +1,392 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.permissions; + + +import java.util.Iterator; + +import com.arsdigita.persistence.OID; + +import com.arsdigita.kernel.Party; +import com.arsdigita.kernel.ACSObject; +import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; +import com.arsdigita.kernel.permissions.PermissionDescriptor; + + +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.table.TableModel; +import com.arsdigita.bebop.table.AbstractTableModelBuilder; +import com.arsdigita.bebop.table.TableColumn; +import com.arsdigita.bebop.table.TableColumnModel; +import com.arsdigita.bebop.table.DefaultTableColumnModel; +import com.arsdigita.bebop.table.TableCellRenderer; +import com.arsdigita.bebop.table.TableHeader; + +import com.arsdigita.portalserver.Icons; + +import org.apache.log4j.Category; + +abstract class GrantsTable extends Table { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/permissions/GrantsTable.java#4 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static Category s_log = Category.getInstance + (GrantsTable.class.getName()); + + private static final String REMOVE_EVENT = "_revoke_all_"; + + private static final String COLUMN_WIDTH = "12%"; + + // These RLs are used by all the control links to get their + // control event values. It's basically a communications + // chanel between getComponent and setControlEvent. + final static RequestLocal s_targetRL = new RequestLocal(); + final static RequestLocal s_adjustCodeRL = new RequestLocal(); + + private static class EditPrivilegeCellRenderer + implements TableCellRenderer { + final PrivilegeDescriptor m_privilege; + final ControlLink m_link; + + EditPrivilegeCellRenderer(PrivilegeDescriptor privilege) { + m_privilege = privilege; + + final String eventName = privilege.getName(); + + m_link = new ControlLink(Icons.RADIO_EMPTY_16) { + public void setControlEvent(PageState ps) { + ps.setControlEvent((Component) s_targetRL.get(ps), + eventName, + (String) s_adjustCodeRL.get(ps)); + } + }; + } + + public Component getComponent(Table table, PageState ps, + Object value, boolean isSelected, + Object key, int row, int column) { + Grant grant = (Grant) value; + + if (grant.basePrivilege.equals(m_privilege)) { + // If the current privilege is equal to the privilege + // this component stands for, return the (*). + return Icons.RADIO_FULL_16; + } else { + // Otherwise set up the control event for the link. + s_targetRL.set(ps, table); + s_adjustCodeRL.set(ps, key); + return m_link; + } + } + } + + private static class ViewPrivilegeCellRenderer + implements TableCellRenderer { + final PrivilegeDescriptor m_privilege; + + ViewPrivilegeCellRenderer(PrivilegeDescriptor privilege) { + m_privilege = privilege; + } + + public Component getComponent(Table table, PageState ps, + Object value, boolean isSelected, + Object key, int row, int column) { + Grant grant = (Grant) value; + + if (grant.basePrivilege.equals(m_privilege)) { + return Icons.RADIO_FULL_GRAYED_16; + } else { + return Icons.RADIO_EMPTY_GRAYED_16; + } + } + } + + private static TableCellRenderer[] s_editCellRenderers; + private static TableCellRenderer[] s_viewCellRenderers; + + static { + int n = Grant.s_interestingPrivileges.length; + s_editCellRenderers = new TableCellRenderer[n]; + s_viewCellRenderers = new TableCellRenderer[n]; + for (int i = 0; i < n; i++) { + s_editCellRenderers[i] = + new EditPrivilegeCellRenderer(Grant.s_interestingPrivileges[i]); + s_viewCellRenderers[i] = + new ViewPrivilegeCellRenderer(Grant.s_interestingPrivileges[i]); + } + } + + // Per-request label for renderer getComponent calls + private final static RequestLocal s_dynamicLabel = new RequestLocal() { + public Object initialValue(PageState ps) { + return new Label(); + } + }; + + public GrantsTable(final RequestLocal grantsRL, + final RequestLocal typesRL, + final boolean isEditable) { + super(); + + setClassAttr("fancy"); + + setModelBuilder(new AbstractTableModelBuilder() { + public TableModel makeModel(Table t, PageState ps) { + final Iterator grants = (Iterator) grantsRL.get(ps); + + return new TableModel() { + Grant m_currentGrant; + String m_currentKey; + + public int getColumnCount() { + return 6; + } + + public Object getElementAt(int index) { + return m_currentGrant; + } + + public Object getKeyAt(int columnIndex) { + return m_currentKey; + } + + public boolean nextRow() { + if (grants.hasNext()) { + m_currentGrant = (Grant) grants.next(); + + s_log.debug("Preparing to display Grant " + + m_currentGrant); + + m_currentKey = m_currentGrant.toString(); + + return true; + } else { + return false; + } + } + }; + } + }); + + TableColumnModel columnModel = new DefaultTableColumnModel(); + + // We assume that whoever uses the GrantsTable will + // be adding a column of their own + + // COLUMN 1: Type Name (may be hidden) + TableColumn typeColumn = new TableColumn(1, "On") { + public boolean isVisible(PageState ps) { + return (typesRL.get(ps) != null); + } + }; + + typeColumn.setCellRenderer(new TableCellRenderer() { + public Component getComponent(Table table, + PageState ps, + Object value, + boolean isSelected, + Object key, + int row, + int column) { + Grant grant = (Grant) value; + Label typeLabel = (Label) s_dynamicLabel.get(ps); + typeLabel.setLabel(grant.objectTypeDisplayName); + return typeLabel; + } + }); + columnModel.add(typeColumn); + + // COLUMNS 2 through N: Privilege entries + TableCellRenderer[] cellRenderers; + + if (isEditable) { + cellRenderers = s_editCellRenderers; + } else { + cellRenderers = s_viewCellRenderers; + } + + for (int i = 0; i < Grant.s_interestingPrivileges.length; i++) { + TableColumn privColumn = new TableColumn + (2 + i, Grant.s_privilegePrettyNames[i]); + + privColumn.setCellRenderer(cellRenderers[i]); + privColumn.setClassAttr("icon"); + privColumn.setHeadClassAttr("icon"); + privColumn.setWidth(COLUMN_WIDTH); + + columnModel.add(privColumn); + } + + // COLUMN N + 1: Optional REMOVE column + if (isEditable) { + TableColumn removeColumn = new TableColumn(5, "Remove"); + + removeColumn.setAlign("center"); + removeColumn.setCellRenderer(new TableCellRenderer() { + final ControlLink m_link = new ControlLink(Icons.TRASH_16) { + public void setControlEvent(PageState ps) { + ps.setControlEvent(GrantsTable.this, + REMOVE_EVENT, + (String) s_adjustCodeRL.get(ps)); + } + }; + + public Component getComponent(Table table, + PageState ps, + Object value, + boolean isSelected, + Object key, + int row, + int column) { + Grant grant = (Grant) value; + + s_adjustCodeRL.set(ps, key); + + return m_link; + } + }); + + removeColumn.setClassAttr("icon"); + removeColumn.setHeadClassAttr("icon"); + removeColumn.setWidth(COLUMN_WIDTH); + + columnModel.add(removeColumn); + } + + setColumnModel(columnModel); + setHeader(new TableHeader(columnModel)); + } + + public void respond(PageState ps) { + String controlEventName = ps.getControlEventName(); + String controlEventValue = ps.getControlEventValue(); + + s_log.debug("Responding to control event \"" + controlEventName + + " => " + controlEventValue + "\""); + + PrivilegeDescriptor newPriv = null; + + found: if (!REMOVE_EVENT.equals(controlEventName)) { + for (int i = 0; i < Grant.s_interestingPrivileges.length; i++) { + PrivilegeDescriptor priv = Grant.s_interestingPrivileges[i]; + String privName = priv.getName(); + + if (privName.equals(controlEventName)) { + newPriv = priv; + break found; + } + } + + throw new IllegalStateException("Unknown control event"); + } + + Grant grant = Grant.unmarshal(ps.getControlEventValue()); + + OID objectOID = new OID + (ACSObject.BASE_DATA_OBJECT_TYPE, grant.objectID); + + OID partyOID = new OID + (Party.BASE_DATA_OBJECT_TYPE, grant.granteeID); + + s_log.debug("Privilege requested is " + newPriv + ". " + + "Existing privilege is " + grant.basePrivilege + "."); + + int oldLevel = Grant.getPrivilegeLevel(grant.basePrivilege); + + if (oldLevel > 0 && newPriv == null) { + // REMOVE_EVENT case 1: There are existing privileges + // other than read. + + s_log.debug("Revoking old privilege. Old privilege was " + + oldLevel + "."); + + PermissionDescriptor createPD = + getPermissionDescriptorHelper(grant, Grant.CREATE, + objectOID, partyOID); + PermissionDescriptor oldPD = + getPermissionDescriptorHelper(grant, oldLevel, + objectOID, partyOID); + PermissionService.revokePermission(createPD); + PermissionService.revokePermission(oldPD); + } else if (oldLevel == 0 && newPriv == null) { + // REMOVE_EVENT case 2: Only existing privilege is read. + + s_log.debug("Revoking old privilege. Old privilege was " + + oldLevel + "."); + + PermissionDescriptor oldPD = + getPermissionDescriptorHelper(grant, oldLevel, + objectOID, partyOID); + PermissionService.revokePermission(oldPD); + } else { + // Add new privileges (but first revoke old ones). + + s_log.debug("Adding new privilege, but first removing old ones."); + + int newLevel = Grant.getPrivilegeLevel(newPriv); + + // Revoke old privileges. + PermissionDescriptor oldPD = + getPermissionDescriptorHelper(grant, oldLevel, + objectOID, partyOID); + PermissionService.revokePermission(oldPD); + + // Grant new privileges. + PermissionDescriptor newPD = + getPermissionDescriptorHelper(grant, newLevel, + objectOID, partyOID); + PermissionService.grantPermission(newPD); + + // Handle create. + PermissionDescriptor createPD = + getPermissionDescriptorHelper(grant, Grant.CREATE, + objectOID, partyOID); + + if (newLevel == Grant.EDIT || newLevel == Grant.ADMIN) { + s_log.debug("Implicitly granting create."); + + PermissionService.grantPermission(createPD); + } else if (oldLevel == Grant.EDIT || oldLevel == Grant.ADMIN) { + // If the new permission grant is one that + // does not require create AND the old permission + // did have create, revoke it. + + s_log.debug("Implicitly revoking create."); + + PermissionService.revokePermission(createPD); + } + } + } + + private PermissionDescriptor getPermissionDescriptorHelper + (Grant grant, int privLevel, OID objectOID, OID partyOID) { + PrivilegeDescriptor priv; + + priv = Grant.s_privileges[privLevel]; + return new PermissionDescriptor(priv, objectOID, partyOID); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/permissions/ObjectPermissionEdit.java b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/ObjectPermissionEdit.java new file mode 100644 index 000000000..4986bd4dc --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/ObjectPermissionEdit.java @@ -0,0 +1,753 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.permissions; + + +import com.arsdigita.portalserver.permissions.util.GlobalizationUtil; + + +import java.util.LinkedList; +import java.util.Collection; +import java.util.HashMap; + +import com.arsdigita.xml.Element; + +import com.arsdigita.util.Assert; + +import com.arsdigita.kernel.ACSObject; +import com.arsdigita.kernel.Party; +import com.arsdigita.kernel.PartyCollection; +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; +import com.arsdigita.kernel.permissions.ObjectPermissionCollection; +import com.arsdigita.kernel.permissions.PermissionService; + +import com.arsdigita.persistence.DataObject; +import com.arsdigita.domain.DomainObjectFactory; + +import com.arsdigita.bebop.*; +import com.arsdigita.bebop.form.*; +import com.arsdigita.bebop.event.*; +import com.arsdigita.bebop.table.*; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.bebop.parameters.BooleanParameter; + +import com.arsdigita.bebop.util.Color; + +import com.arsdigita.portalserver.*; + +import com.arsdigita.util.Assert; +import org.apache.log4j.Category; + + +public class ObjectPermissionEdit extends CompoundComponent { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/permissions/ObjectPermissionEdit.java#3 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static Category s_log = Category.getInstance + (ObjectPermissionEdit.class.getName()); + + // Heavily-reused per-request label for renderer getComponent calls + private final static RequestLocal s_dynamicLabel = new RequestLocal() { + public Object initialValue(PageState ps) { + return new Label(); + } + }; + + + private static class ObjectGrantsTable extends GrantsTable { + static void getGrantsHelper(ACSObject object, + Collection types, + LinkedList ordering) { + HashMap canonicalMap = new HashMap(); + + ObjectPermissionCollection opc = + PermissionService.getDirectGrantedPermissions(object.getOID()); + + try { + while (opc.next()) { + s_log.debug + ("Current grant in loop is " + opc.getPrivilege()); + + if (opc.isInherited() + // Skip create privileges. They are created + // and destroyed implicitly when the other + // privileges are used. + || opc.getPrivilege().equals + (PrivilegeDescriptor.CREATE)) { + continue; + } + + Grant grant = new Grant(); + + grant.populatePrivilege(opc.getPrivilege()); + + if (grant.level < 0) { + continue; + } + + if (grant.objectType != null + && types != null + && !types.contains(grant.objectType)) { + continue; + } + + grant.granteeID = opc.getGranteeID(); + grant.granteeName = opc.getGranteeName(); + grant.granteeIsUser = opc.granteeIsUser(); + grant.objectID = object.getID(); + grant.objectName = object.getDisplayName(); + + if (!canonicalMap.containsKey(grant)) { + ordering.add(grant); + canonicalMap.put(grant, grant); + continue; + } + + Grant canonical = (Grant) canonicalMap.get(grant); + + if (grant.level > canonical.level) { + canonical.level = grant.level; + canonical.basePrivilege = grant.basePrivilege; + } + } + } finally { + opc.close(); + } + } + + + public ObjectGrantsTable(RequestLocal grantsRL, + RequestLocal typesRL, + boolean isEditable) { + super(grantsRL, typesRL, isEditable); + + // COLUMN 0: The party with the grant + TableColumn partyColumn = new TableColumn(0, "User or Role"); + partyColumn.setCellRenderer(new TableCellRenderer() { + final RequestLocal m_userNameDisplay = new RequestLocal() { + public Object initialValue(PageState ps) { + SimpleContainer result = new SimpleContainer(); + result.add(Icons.USER_16); + result.add((Component) s_dynamicLabel.get(ps)); + return result; + } + }; + final RequestLocal m_groupNameDisplay = new RequestLocal() { + public Object initialValue(PageState ps) { + SimpleContainer result = new SimpleContainer(); + result.add(Icons.GROUP_16); + result.add((Component)s_dynamicLabel.get(ps)); + return result; + } + }; + public Component getComponent(Table table, + PageState ps, + Object value, + boolean isSelected, + Object key, + int row, + int column) { + Grant grant = (Grant)value; + Label nameLabel = (Label)s_dynamicLabel.get(ps); + nameLabel.setLabel( (String) GlobalizationUtil.globalize("cw.cw.permissions.").localize() + grant.granteeName); + if (grant.granteeIsUser) { + return (Component) m_userNameDisplay.get(ps); + } else { + return (Component) m_groupNameDisplay.get(ps); + } + } + }); + getColumnModel().add(0, partyColumn); + + } + } + + + + private static class ObjectDirectGrantsTable extends ObjectGrantsTable { + public ObjectDirectGrantsTable(final RequestLocal objectRL, + final RequestLocal typesRL) { + super(new RequestLocal() { + public Object initialValue(PageState ps) { + LinkedList ordering = new LinkedList(); + getGrantsHelper((ACSObject) objectRL.get(ps), + (Collection) typesRL.get(ps), + ordering); + return ordering.iterator(); + } + }, typesRL, true); + } + + } + + + + private static class ObjectIndirectGrantsTable extends ObjectGrantsTable { + public ObjectIndirectGrantsTable(final RequestLocal objectRL, + final RequestLocal typesRL) { + super(new RequestLocal() { + public Object initialValue(PageState ps) { + LinkedList ordering = new LinkedList(); + + ACSObject object = (ACSObject) objectRL.get(ps); + Collection types = (Collection) typesRL.get(ps); + + // FIXME: May need to do this by getting the OID + // and doing a verifySubtype check + while (!(object instanceof PortalSite)) { + DataObject ctx = PermissionService.getContext(object); + if (ctx == null) { + break; + } + object = (ACSObject) DomainObjectFactory.newInstance + (ctx); + getGrantsHelper(object, types, ordering); + } + + return ordering.iterator(); + } + }, typesRL, false); + + // 'Target' column + TableColumn targetColumn = new TableColumn(1, "On"); + targetColumn.setCellRenderer(new TableCellRenderer() { + public Component getComponent(Table table, + PageState ps, + Object value, + boolean isSelected, + Object key, + int row, + int column) { + Grant grant = (Grant) value; + Label l = (Label) s_dynamicLabel.get(ps); + l.setLabel(grant.objectName); + return l; + } + }); + getColumnModel().add(1, targetColumn); + } + } + + private class MainDisplay extends CompoundComponent { + MainDisplay(final RequestLocal objectRL, + final RequestLocal directTypesRL, + final RequestLocal indirectTypesRL, + final ActionListener onAddClick) { + super(new BoxPanel(BoxPanel.VERTICAL)); + + + // Header for direct permission list + final GridPanel directHeader = new GridPanel(2); + + Label directLabel = + new Label(GlobalizationUtil.globalize("cw.cw.permissions.view_and_manage_specific_permissions")); + directLabel.setFontWeight(Label.BOLD); + directHeader.add(directLabel, GridPanel.LEFT); + ActionLink newGrantLink = new ActionLink( (String) GlobalizationUtil.globalize("cw.cw.permissions.add_user_or_role").localize()); + newGrantLink.setClassAttr("actionLink"); + newGrantLink.addActionListener(onAddClick); + directHeader.add(newGrantLink, GridPanel.RIGHT); + add(directHeader); + + add(new Label("The following users and roles have specific " + + "privileges on this knowledge item:")); + + // Direct permission list + Table directTable = new ObjectDirectGrantsTable + (objectRL, directTypesRL); + directTable.setCellPadding("5"); + Label directEmptyView = new Label("No specific privileges are " + + "defined on this item."); + directEmptyView.setFontWeight(Label.ITALIC); + directTable.setEmptyView(directEmptyView); + add(directTable); + + add(new Label(" ")); + + // Header for indirect permission list + Label indirectLabel = new Label(GlobalizationUtil.globalize("cw.cw.permissions.view_general_permissions")); + indirectLabel.setFontWeight(Label.BOLD); + add(indirectLabel); + + add(new Label("The following users and roles have broader " + + "privileges applying to this and other knowledge " + + "items. Note that these are inherited privileges " + + "and can only be changed from the location given " + + "in the \"On\" column.")); + + + // Indirect permission list + Table indirectTable = new ObjectIndirectGrantsTable + (objectRL, indirectTypesRL); + + indirectTable.setCellPadding("5"); + Label indirectEmpty = new Label("No general permissions apply " + + "to this item."); + indirectEmpty.setFontWeight(Label.ITALIC); + indirectTable.setEmptyView(indirectEmpty); + add(indirectTable); + + } + + } + + // Maximum party search results + private static final long MAX_RESULTS = 20; + + private class NewGrantDisplay extends CompoundComponent { + // RequestLocal storing the object + private final RequestLocal m_objectRL; + + // Collection of 'relevant types' + private final RequestLocal m_typesRL; + + // Parameter containing user's search string + private final StringParameter m_queryParam = + new StringParameter("queryParam"); + + // Flag indicating whether or not to limit search to current + // workspace's participants + private final BooleanParameter m_limitParam = + new BooleanParameter("limitParam"); + + private final RequestLocal m_partiesRL = new RequestLocal() { + public Object initialValue(PageState ps) { + PortalSite psite = + PortalSite.getCurrentPortalSite(ps.getRequest()); + + String queryString = (String) ps.getValue(m_queryParam); + + PartyCollection parties; + Boolean limit = (Boolean) ps.getValue(m_limitParam); + + if (limit != null && limit.booleanValue()) { + parties = psite.getParticipants(); + } else { + parties = Party.retrieveAllParties(); + } + + parties.filter(queryString); + + return parties; + } + }; + + + private void clearQuery(PageState ps) { + ps.setValue(m_queryParam, null); + ps.setValue(m_limitParam, null); + } + + private void setQuery(PageState ps, String query, Boolean limit) { + ps.setValue(m_queryParam, query); + ps.setValue(m_limitParam, limit); + } + + private boolean haveQuery(PageState ps) { + return (ps.getValue(m_queryParam) != null); + } + + private PartyCollection getQueryResults(PageState ps) { + if (!haveQuery(ps)) { + throw new IllegalStateException("No query specified."); + } + return (PartyCollection) m_partiesRL.get(ps); + } + + private class BoldLabel extends Label { + public BoldLabel(String text) { + super(text); + setFontWeight(Label.BOLD); + } + } + + private class MyAddGrantForm extends AddGrantForm { + public MyAddGrantForm(String name, + Widget partyWidget, + final RequestLocal errorMessageRL) { + super(name, new GridPanel(4), errorMessageRL); + setMethod(Form.POST); + + // Row 1: Labels + add(new BoldLabel("Select Grantee:")); + + add(new BoldLabel("On:") { + public void generateXML(PageState ps, Element parent) { + Collection types = (Collection)m_typesRL.get(ps); + + if ((types == null) || (types.size() <= 1)) { + parent.newChildElement("bebop:label", BEBOP_XML_NS); + return; + } else { + super.generateXML(ps, parent); + } + } + }); + + add(new BoldLabel("Privilege:")); + + add(new Label("")); + + // Row 2: Widgets + + // Create a hidden widget for the objectID + add(new Hidden(getObjectParameter())); + + // Use provided widget for partyID + partyWidget.setParameterModel(getPartyParameter()); + add(partyWidget); + + // Selection widget for the type. + add(new TypeSingleSelect(getTypeParameter(), m_typesRL)); + + // Selection widget for the privilege + add(new PrivilegeSingleSelect(getPrivilegeParameter())); + + // Submission button + add(new Submit("Grant")); + + // Init listener to initialize the objectID parameter + addInitListener(new FormInitListener() { + public void init(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + FormData fd = ev.getFormData(); + fd.put(getObjectParameter().getName(), + ((ACSObject)m_objectRL.get(ps)).getID()); + } + }); + + addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + NewGrantDisplay.this.fireCompletionEvent(ps); + } + }); + } + } + + NewGrantDisplay(RequestLocal objectRL, + RequestLocal typesRL) { + m_objectRL = objectRL; + m_typesRL = typesRL; + + // This RL makes available a PartyCollection containing + // the result of the specified query + + final BoxPanel screen1 = new BoxPanel(BoxPanel.VERTICAL) { + public boolean isVisible(PageState ps) { + if (!haveQuery(ps)) { + return true; + } + PartyCollection pc = + NewGrantDisplay.this.getQueryResults(ps); + long n = pc.size(); + return (n == 0 || n > MAX_RESULTS); + } + }; + add(screen1); + + + Label roleFormTitle = new BoldLabel(""); + roleFormTitle.addPrintListener(new PrintListener() { + public void prepare(PrintEvent ev) { + PageState ps = ev.getPageState(); + Label tgt = (Label)ev.getTarget(); + PortalSite psite = + PortalSite.getCurrentPortalSite(ps.getRequest()); + tgt.setLabel("Grant privilege to a role from the \"" + + psite.getTitle() + "\" portal:"); + } + }); + screen1.add(roleFormTitle); + + // Form for granting to a portal role + final RequestLocal rfErrorMessageRL = new RequestLocal(); + + SingleSelect roleField = new SingleSelect("roleField"); + roleField.setPrintListener(new PrintListener() { + public void prepare(PrintEvent ev) { + SingleSelect tgt = (SingleSelect)ev.getTarget(); + PageState ps = ev.getPageState(); + PortalSite psite = + PortalSite.getCurrentPortalSite(ps.getRequest()); + RoleCollection rc = psite.getRoles(); + while (rc.next()) { + Option o = new Option + (rc.getID().toString(), rc.getRoleName()); + tgt.addOption(o); + } + } + }); + Form roleForm = new MyAddGrantForm("roleGrant", + roleField, + rfErrorMessageRL); + screen1.add(roleForm); + + // Error message display + screen1.add(new ErrorMessageDisplay(rfErrorMessageRL)); + + + + // Toplevel search label + screen1.add(new BoldLabel("Search for a user or role to recieve " + + "a privilege:")); + + Form otherSearch = new Form("otherSearch", new GridPanel(2)); + otherSearch.setRedirecting(true); + + final TextField queryField = new TextField("query"); + otherSearch.add(queryField); + + otherSearch.add(new Submit("Search")); + + Label limitLabel = new Label(""); + limitLabel.addPrintListener(new PrintListener() { + public void prepare(PrintEvent ev) { + Label tgt = (Label)ev.getTarget(); + PageState ps = ev.getPageState(); + PortalSite psite = + PortalSite.getCurrentPortalSite(ps.getRequest()); + tgt.setLabel("Limit search to \"" + psite.getTitle() + + "\" participants"); + } + }); + + final CheckboxGroup limitToParticipants = + new CheckboxGroup("limitToParticipants"); + String[] limitDefault = { "yes" }; + limitToParticipants.setDefaultValue(limitDefault); + limitToParticipants.addOption(new Option("yes", limitLabel)); + otherSearch.add(limitToParticipants); + + otherSearch.add(new Label("")); + + // Label to display when no matches are found + Label noMatchLabel = new Label(GlobalizationUtil.globalize("cw.cw.permissions.no_matches_found")) { + public boolean isVisible(PageState ps) { + if (!haveQuery(ps)) { + return false; + } + + PartyCollection pc = getQueryResults(ps); + + if (pc == null || pc.size() > 0) { + return false; + } else { + return true; + } + } + }; + noMatchLabel.setColor(Color.red); + otherSearch.add(noMatchLabel); + + // Label to display when too many matches are found. + Label tooManyLabel = + new Label(GlobalizationUtil.globalize("cw.cw.permissions.too_many_matches_refine_your_search")) { + public boolean isVisible(PageState ps) { + if (!haveQuery(ps)) { + return false; + } + + PartyCollection pc = getQueryResults(ps); + + if (pc == null || pc.size() <= MAX_RESULTS) { + return false; + } else { + return true; + } + } + }; + tooManyLabel.setColor(Color.red); + otherSearch.add(tooManyLabel); + + + + // SECOND Add screen: Search results + final BoxPanel screen2 = new BoxPanel(BoxPanel.VERTICAL) { + public boolean isVisible(PageState ps) { + if (!haveQuery(ps)) { + return false; + } + PartyCollection pc = getQueryResults(ps); + long n = pc.size(); + return (n > 0 && n <= MAX_RESULTS); + } + }; + add(screen2); + + otherSearch.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + String queryString = (String)queryField.getValue(ps); + String[] limit = (String[])limitToParticipants.getValue(ps); + if (limit != null && limit.length > 0) { + setQuery(ps, queryString, Boolean.TRUE); + } else { + setQuery(ps, queryString, Boolean.FALSE); + } + } + }); + + screen1.add(otherSearch); + + screen1.add(new Label("")); + + ActionLink returnLink = + new ActionLink( (String) GlobalizationUtil.globalize("cw.cw.permissions.return_to_current_permissions_view").localize()); + returnLink.setClassAttr("actionLink"); + returnLink.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + fireCompletionEvent(ev.getPageState()); + } + }); + screen1.add(returnLink); + + + // Build Search results form + + RequestLocal pfErrorMessageRL = new RequestLocal(); + + RadioGroup partyField = new RadioGroup("partyField"); + partyField.setLayout(RadioGroup.VERTICAL); + partyField.setPrintListener(new PrintListener() { + public void prepare(PrintEvent ev) { + PageState ps = ev.getPageState(); + RadioGroup target = (RadioGroup)ev.getTarget(); + PartyCollection parties = getQueryResults(ps); + while (parties.next()) { + target.addOption(new Option(parties.getID().toString(), + parties.getDisplayName())); + } + } + }); + + + Form partyForm = new MyAddGrantForm("partyGrant", + partyField, + pfErrorMessageRL); + + screen2.add(partyForm); + + screen2.add(new ErrorMessageDisplay(pfErrorMessageRL)); + + ActionLink newSearchLink = new ActionLink( (String) GlobalizationUtil.globalize("cw.cw.permissions.try_a_new_search").localize()); + newSearchLink.setClassAttr("actionLink"); + newSearchLink.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + clearQuery(ev.getPageState()); + } + }); + screen2.add(newSearchLink); + + ActionLink returnToMainLink = + new ActionLink( (String) GlobalizationUtil.globalize("cw.cw.permissions.return_to_current_permissions_view").localize()); + returnToMainLink.setClassAttr("actionLink"); + returnToMainLink.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + NewGrantDisplay.this.fireCompletionEvent(ev.getPageState()); + } + }); + screen2.add(returnToMainLink); + } + + + public void fireCompletionEvent(PageState ps) { + clearQuery(ps); + super.fireCompletionEvent(ps); + } + + public void register(Page p) { + p.addComponentStateParam(this, m_queryParam); + p.addComponentStateParam(this, m_limitParam); + super.register(p); + } + + } + + + public void register(Page p) { + // Assert.assertTrue((p instanceof CWPage), + Assert.isTrue((p instanceof CWPage), + "ObjectPermissionEdit may only be used on " + + "instances of CWPage."); + super.register(p); + } + + + private void initialize(RequestLocal objectRL, + RequestLocal directTypesRL, + RequestLocal indirectTypesRL) { + + final SimpleContainer c = (SimpleContainer)getContainer(); + + final Completable newGrantDisplay = + new NewGrantDisplay(objectRL, directTypesRL) { + public void register(Page p) { + super.register(p); + p.setVisibleDefault(this, false); + } + }; + + ActionListener onAddClick = new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + CWPage page = (CWPage)ps.getPage(); + page.goModal(ps, newGrantDisplay); + } + }; + + final Component mainDisplay = + new MainDisplay(objectRL, + directTypesRL, + indirectTypesRL, + onAddClick); + + newGrantDisplay.addCompletionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + CWPage page = (CWPage)ps.getPage(); + page.goUnmodal(ps); + } + }); + + add(mainDisplay); + add(newGrantDisplay); + } + + + + public ObjectPermissionEdit(final RequestLocal objectRL) { + super(new SimpleContainer()); + initialize(objectRL, new RequestLocal(), new RequestLocal()); + /* + { + public Object initialValue(PageState ps) { + ACSObject object = (ACSObject)objectRL.get(ps); + HashSet result = new HashSet(1); + result.add(object.getObjectType()); + return result; + } + }); + */ + + } + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/permissions/PartyPermissionEdit.java b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/PartyPermissionEdit.java new file mode 100644 index 000000000..3dae878e2 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/PartyPermissionEdit.java @@ -0,0 +1,382 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.permissions; + + +import com.arsdigita.portalserver.permissions.util.GlobalizationUtil; + + +import java.util.*; +import java.util.List; +import com.arsdigita.web.*; +import com.arsdigita.kernel.*; +import com.arsdigita.kernel.permissions.*; +import com.arsdigita.portalserver.*; +import com.arsdigita.bebop.*; +import com.arsdigita.bebop.table.*; +import com.arsdigita.bebop.form.*; +import com.arsdigita.bebop.event.*; + +import com.arsdigita.xml.Element; + +import org.apache.log4j.Category; + +public class PartyPermissionEdit extends CompoundComponent { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/permissions/PartyPermissionEdit.java#3 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static Category s_log = Category.getInstance + (PartyPermissionEdit.class.getName()); + + // Heavily-reused per-request label for renderer getComponent calls + private final static RequestLocal s_dynamicLabel = new RequestLocal() { + public Object initialValue(PageState ps) { + return new Label(); + } + }; + + private static class PartyGrantsTable extends GrantsTable { + static void getGrantsHelper(Party party, + Application application, + Collection types, + LinkedList ordering) { + HashMap canonicalMap = new HashMap(); + + Iterator privIter = PermissionService.getDirectPrivileges + (application.getOID(), party.getOID()); + + while (privIter.hasNext()) { + Grant grant = new Grant(); + + PrivilegeDescriptor priv = + (PrivilegeDescriptor) privIter.next(); + + s_log.debug("Current grant in loop is " + priv); + + if (priv.equals(PrivilegeDescriptor.CREATE)) { + // Skip create privs. They are created and + // destroyed implicitly through the other + // privileges, read, edit, and manage. + continue; + } + + grant.populatePrivilege(priv); + + if (grant.level < 0) { + continue; + } + + if (grant.objectType != null && + types != null && + !types.contains(grant.objectType)) { + continue; + } + + grant.granteeID = party.getID(); + grant.granteeName = party.getName(); + grant.granteeIsUser = (party instanceof User); + grant.objectID = application.getID(); + grant.objectName = application.getDisplayName(); + + if (!canonicalMap.containsKey(grant)) { + ordering.add(grant); + canonicalMap.put(grant, grant); + continue; + } + + Grant canonical = (Grant)canonicalMap.get(grant); + + if (grant.level > canonical.level) { + canonical.level = grant.level; + canonical.basePrivilege = grant.basePrivilege; + } + } + } + + public PartyGrantsTable(final RequestLocal portalsiteRL, + final RequestLocal partyRL, + final RequestLocal typesRL) { + super(new RequestLocal() { + public Object initialValue(PageState ps) { + LinkedList ordering = new LinkedList(); + + PortalSite psite = + (PortalSite)portalsiteRL.get(ps); + Party party = (Party)partyRL.get(ps); + Collection types = (Collection)typesRL.get(ps); + + getGrantsHelper(party, psite, types, ordering); + + ApplicationCollection ac = + psite.getFullPagePortalSiteApplications(); + + while (ac.next()) { + getGrantsHelper(party, + ac.getApplication(), + types, + ordering); + } + + return ordering.iterator(); + } + }, typesRL, true); + + TableColumn appColumn = new TableColumn(0, "On:"); + appColumn.setCellRenderer(new TableCellRenderer() { + public Component getComponent(Table table, PageState ps, + Object value, boolean isSelected, + Object key, int row, int col) { + Grant grant = (Grant)value; + Label l = (Label)s_dynamicLabel.get(ps); + l.setLabel(grant.objectName); + return l; + } + }); + appColumn.setWidth("150"); + getColumnModel().add(0, appColumn); + } + } + + private static class BoldLabel extends Label { + public BoldLabel(String text) { + super(text); + setFontWeight(Label.BOLD); + } + } + + private static class MyAddGrantForm extends AddGrantForm { + + private RequestLocal m_portalsiteRL; + private RequestLocal m_partyRL; + private RequestLocal m_typesRL; + private RequestLocal m_errorMessageRL; + private ActionListener m_onComplete; + + private RequestLocal m_targetsRL = new RequestLocal() { + public Object initialValue(PageState ps) { + List result = new ArrayList(); + + Party party = (Party) m_partyRL.get(ps); + PortalSite psite = + (PortalSite) m_portalsiteRL.get(ps); + PermissionDescriptor perm = + new PermissionDescriptor(PrivilegeDescriptor.READ, + psite, + party); + if (!PermissionService.checkDirectPermission(perm)) { + result.add(new Option(psite.getID().toString(), + psite.getDisplayName())); + } + + ApplicationCollection ac = + psite.getFullPagePortalSiteApplications(); + while (ac.next()) { + Application app = ac.getApplication(); + perm = + new PermissionDescriptor(PrivilegeDescriptor.READ, + app, + party); + if (!PermissionService.checkDirectPermission(perm)) { + result.add(new Option(app.getID().toString(), + app.getDisplayName())); + } + } + + return result; + } + }; + + private Submit m_cancel = new Submit("Return"); + + private MyAddGrantForm(RequestLocal portalsiteRL, + RequestLocal partyRL, + RequestLocal typesRL, + RequestLocal errorMessageRL, + ActionListener onComplete) { + super("addGrant", new BoxPanel(), errorMessageRL); + setMethod(Form.POST); + + m_portalsiteRL = portalsiteRL; + m_partyRL = partyRL; + m_typesRL = typesRL; + m_errorMessageRL = errorMessageRL; + m_onComplete = onComplete; + + final GridPanel widgets = new GridPanel(4); + + // Row 1: Labels + widgets.add(new BoldLabel("Select Target:")); + + widgets.add(new BoldLabel("On:") { + public void generateXML(PageState ps, Element parent) { + Collection types = (Collection) m_typesRL.get(ps); + if ((types == null) || (types.size() <= 1)) { + parent.newChildElement("bebop:label", BEBOP_XML_NS); + return; + } else { + super.generateXML(ps, parent); + } + } + }); + + widgets.add(new BoldLabel("Privilege:")); + + widgets.add(new Label("")); + + // Row 2: Widgets + + // Create a hidden widget for the partyID + add(new Hidden(getPartyParameter())); + + SingleSelect objectSelect = + new SingleSelect(getObjectParameter()); + objectSelect.setPrintListener(new PrintListener() { + public void prepare(PrintEvent ev) { + SingleSelect target = (SingleSelect)ev.getTarget(); + PageState ps = ev.getPageState(); + List options = (List) m_targetsRL.get(ps); + for (Iterator it = options.iterator(); it.hasNext(); ) { + target.addOption((Option) it.next()); + } + } + }); + widgets.add(objectSelect); + + // Selection widget for the type. + widgets.add(new TypeSingleSelect(getTypeParameter(), typesRL)); + + // Selection widget for the privilege + widgets.add(new PrivilegeSingleSelect(getPrivilegeParameter())); + + // Submission button + final Submit grant = new Submit("Grant"); + widgets.add(grant); + add(widgets); + + add(new ErrorMessageDisplay(errorMessageRL)); + + add(m_cancel); + + addSubmissionListener(new FormSubmissionListener() { + public void submitted(FormSectionEvent evt) + throws FormProcessException { + PageState ps = evt.getPageState(); + if (m_cancel.isSelected(ps)) { + ps.reset(MyAddGrantForm.this); + m_onComplete.actionPerformed( + new ActionEvent(MyAddGrantForm.this, ps) + ); + throw new FormProcessException("cancel"); + } + } + }); + + // Init listener to initialize the objectID parameter + addInitListener(new FormInitListener() { + public void init(FormSectionEvent ev) + throws FormProcessException { + PageState ps = ev.getPageState(); + FormData fd = ev.getFormData(); + fd.put(getPartyParameter().getName(), + ((Party) m_partyRL.get(ps)).getID()); + List targets = (List) m_targetsRL.get(ps); + if (targets.size() == 0) { + widgets.setVisible(ps, false); + m_cancel.setVisible(ps, true); + throw new FormValidationException( + "There are no objects that this " + + "party can be granted permission on." + ); + } + } + }); + } + + public MyAddGrantForm(RequestLocal portalsiteRL, RequestLocal partyRL, + RequestLocal typesRL, + ActionListener onComplete) { + this(portalsiteRL, partyRL, typesRL, new RequestLocal(), + onComplete); + } + + public void register(Page p) { + super.register(p); + p.setVisibleDefault(m_cancel, false); + } + + protected void fireProcess(FormSectionEvent evt) + throws FormProcessException { + super.fireProcess(evt); + + PageState ps = evt.getPageState(); + m_onComplete.actionPerformed( + new ActionEvent(MyAddGrantForm.this, ps) + ); + } + + } + + + public PartyPermissionEdit(String title, + RequestLocal portalsiteRL, + RequestLocal partyRL) { + super(new ModalContainer()); + + final ModalContainer container = (ModalContainer)getContainer(); + + final BoxPanel mainDisplay = new BoxPanel(); + mainDisplay.setWidth("100%"); + container.add(mainDisplay); + container.setDefaultComponent(mainDisplay); + + ActionListener returnToMain = new ActionListener() { + public void actionPerformed(ActionEvent ev) { + container.setVisibleComponent(ev.getPageState(), mainDisplay); + } + }; + final MyAddGrantForm addForm = new MyAddGrantForm(portalsiteRL, + partyRL, + new RequestLocal(), + returnToMain); + container.add(addForm); + + + GridPanel header = new GridPanel(2); + // header.setWidth("100%"); + Label titleLabel = new Label(title); + titleLabel.setFontWeight(Label.BOLD); + header.add(titleLabel, BoxPanel.LEFT); + + ActionLink grantLink = new ActionLink( (String) GlobalizationUtil.globalize("cw.cw.permissions.add_a_privilege").localize()); + grantLink.setClassAttr("actionLink"); + grantLink.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + container.setVisibleComponent(ev.getPageState(), addForm); + } + }); + header.add(grantLink, BoxPanel.RIGHT); + mainDisplay.add(header); + + mainDisplay.add(new PartyGrantsTable(portalsiteRL, + partyRL, + new RequestLocal())); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/permissions/PrivilegeSingleSelect.java b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/PrivilegeSingleSelect.java new file mode 100644 index 000000000..4f7956df4 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/PrivilegeSingleSelect.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.permissions; + +import com.arsdigita.bebop.form.*; +import com.arsdigita.bebop.parameters.*; +import com.arsdigita.kernel.permissions.*; + +class PrivilegeSingleSelect extends SingleSelect { + public PrivilegeSingleSelect(ParameterModel param) { + super(param); + for (int i = 0; i < Grant.s_interestingPrivileges.length; i++) { + PrivilegeDescriptor priv = Grant.s_interestingPrivileges[i]; + String display = Grant.s_privilegePrettyNames[i]; + addOption(new Option(priv.getName(), display)); + } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/permissions/TypeSingleSelect.java b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/TypeSingleSelect.java new file mode 100644 index 000000000..53cc0b0e3 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/TypeSingleSelect.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.permissions; + +import java.util.*; +import com.arsdigita.bebop.parameters.*; +import com.arsdigita.bebop.form.*; +import com.arsdigita.bebop.*; +import com.arsdigita.bebop.event.*; +import com.arsdigita.xml.Element; +import com.arsdigita.persistence.metadata.ObjectType; + + +class TypeSingleSelect extends SingleSelect { + private RequestLocal m_typesRL; + + public TypeSingleSelect(ParameterModel param, + RequestLocal typesRL) { + super(param); + + m_typesRL = typesRL; + + addOption(new Option(AddGrantForm.ALL_TYPES, + "All Contained Items")); + setPrintListener(new PrintListener() { + public void prepare(PrintEvent ev) { + SingleSelect tgt = (SingleSelect)ev.getTarget(); + PageState ps = ev.getPageState(); + Iterator types = + ((Collection)m_typesRL.get(ps)).iterator(); + while (types.hasNext()) { + ObjectType type = (ObjectType)types.next(); + tgt.addOption(new Option(type.getQualifiedName(), + type.getName())); + } + } + }); + } + + public void generateXML(PageState ps, Element parent) { + Collection types = (Collection)m_typesRL.get(ps); + if (types == null) { + parent.newChildElement("bebop:label", BEBOP_XML_NS); + return; + } else { + super.generateXML(ps, parent); + } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/permissions/ui/CwResources.properties b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/ui/CwResources.properties new file mode 100644 index 000000000..4530ac663 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/ui/CwResources.properties @@ -0,0 +1,9 @@ +cw.cw.permissions.= +cw.cw.permissions.view_and_manage_specific_permissions=View and Manage Specific Permissions +cw.cw.permissions.add_user_or_role=Add User or Role +cw.cw.permissions.view_general_permissions=View General Permissions +cw.cw.permissions.no_matches_found=No matches found. +cw.cw.permissions.too_many_matches_refine_your_search=Too many matches. Refine your search. +cw.cw.permissions.return_to_current_permissions_view=Return to current permissions view +cw.cw.permissions.try_a_new_search=Try a new search +cw.cw.permissions.add_a_privilege=Add a privilege diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/permissions/util/GlobalizationUtil.java b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/util/GlobalizationUtil.java new file mode 100644 index 000000000..7f715397e --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/permissions/util/GlobalizationUtil.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.permissions.util; + +import com.arsdigita.globalization.Globalized; +import com.arsdigita.globalization.GlobalizedMessage; + +/** + *

    + * . + * Contains methods to simplify globalizing keys + *

    + * + * @author sarnold@redhat.com + * @version $Revision: #3 $ $Date: 2004/08/17 $ + */ + +public class GlobalizationUtil implements Globalized { + + private static final String BUNDLE_NAME = "com.arsdigita.portalserver.permissions.ui.CwResources"; + + public static GlobalizedMessage globalize(String key) { + return new GlobalizedMessage(key, BUNDLE_NAME); + } + public static GlobalizedMessage globalize(String key, Object[] args) { + return new GlobalizedMessage(key, BUNDLE_NAME, args); + + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/personal/Initializer.java b/ccm-portalserver/src/com/arsdigita/portalserver/personal/Initializer.java new file mode 100644 index 000000000..32a2e0f3a --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/personal/Initializer.java @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.personal; + +import org.apache.log4j.Category; +import com.arsdigita.web.ApplicationType; +import com.arsdigita.web.Application; +import com.arsdigita.web.ApplicationSetup; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.TransactionContext; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.kernel.ACSObjectInstantiator; +import com.arsdigita.kernel.KernelExcursion; +import com.arsdigita.kernel.Kernel; +import com.arsdigita.domain.DomainObject; +import com.arsdigita.initializer.Configuration; +import com.arsdigita.initializer.InitializationException; +import com.arsdigita.portal.PortletType; +import com.arsdigita.portal.apportlet.AppPortletSetup; + +/** + *

    Experimental

    + * + * @author Justin Ross + * @version $Id: //portalserver/dev/src/com/arsdigita/portalserver/personal/Initializer.java#12 $ + */ +public class Initializer implements com.arsdigita.initializer.Initializer { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/personal/Initializer.java#12 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static Category s_log = Category.getInstance + (Initializer.class); + + private Configuration m_conf = new Configuration(); + + public Initializer() throws InitializationException { + /* Empty */ + } + + public Configuration getConfiguration() { + return m_conf; + } + + public void startup() { + s_log.info("Initializing Personal Portal..."); + + TransactionContext txn = + SessionManager.getSession().getTransactionContext(); + + txn.beginTxn(); + + ApplicationType creatorAppType = + setupPersonalPortalCreatorApplication(); + + // Create an instance of the personal portal creator at + // /personal-portal/. + + boolean creatorInstalled = Application.isInstalled + (PersonalPortalCreator.BASE_DATA_OBJECT_TYPE, + "/personal-portal/"); + + if (!creatorInstalled) { + + KernelExcursion ex = new KernelExcursion() { + protected void excurse() { + setParty(Kernel.getSystemParty()); + Application creatorApp = Application.createApplication + (PersonalPortalCreator.BASE_DATA_OBJECT_TYPE, + "personal-portal", "Personal Portal Creator", null); + creatorApp.save(); + } + }; + ex.run(); + + + } + + ApplicationType pwAppType = setupPersonalPortalApplication(); + + setupMyPortalsPortlet(); + + txn.commitTxn(); + + s_log.info("Done initializing Personal Portal."); + } + + private ApplicationType setupPersonalPortalCreatorApplication() { + ApplicationSetup setup = new ApplicationSetup(s_log); + + setup.setApplicationObjectType + (PersonalPortalCreator.BASE_DATA_OBJECT_TYPE); + setup.setKey("personal-portal-creator"); + setup.setTitle("Personal Portal Creator"); + setup.setDescription("Responsible for creating personal portals."); + // db based stylesheets nolonger used + // setup.setStylesheet("/packages/portalserver/xsl/portalserver.xsl"); + setup.setDispatcherClass + ("com.arsdigita.portalserver.personal.PersonalPortalCreatorDispatcher"); + setup.setPortalApplication(false); + setup.setInstantiator(new ACSObjectInstantiator() { + protected DomainObject doNewInstance(DataObject dataObject) { + return new PersonalPortalCreator(dataObject); + } + }); + + return setup.run(); + } + + private ApplicationType setupPersonalPortalApplication() { + ApplicationSetup setup = new ApplicationSetup(s_log); + + setup.setApplicationObjectType(PersonalPortal.BASE_DATA_OBJECT_TYPE); + setup.setKey("personal-portal"); + setup.setTitle("Personal Portal"); + setup.setDescription("A portal for an individual."); + // setup.setStylesheet("/packages/portalserver/xsl/portalserver.xsl"); + setup.setDispatcherClass + ("com.arsdigita.portalserver.personal.PersonalPortalDispatcher"); + setup.setPortalApplication(false); + setup.setInstantiator(new ACSObjectInstantiator() { + protected DomainObject doNewInstance(DataObject dataObject) { + return new PersonalPortal(dataObject); + } + }); + + ApplicationType type = setup.run(); + + // XXX This must go after setup.run(). Need more elegant approach. + new PersonalPortalConfig(); + + return type; + } + + private void setupMyPortalsPortlet() { + AppPortletSetup setup = new AppPortletSetup(s_log); + + setup.setPortletObjectType + (MyPortalsPortlet.BASE_DATA_OBJECT_TYPE); + setup.setTitle("My Portals"); + setup.setDescription + ("Displays links to portals to which you belong."); + setup.setProfile(PortletType.NARROW_PROFILE); + setup.setPortalApplication(true); + setup.setInstantiator(new ACSObjectInstantiator() { + public DomainObject doNewInstance(DataObject dataObject) { + return new MyPortalsPortlet(dataObject); + } + }); + + setup.run(); + } + + public void shutdown() { + /* Empty */ + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/personal/MyItemsApplication.java b/ccm-portalserver/src/com/arsdigita/portalserver/personal/MyItemsApplication.java new file mode 100644 index 000000000..737b434ee --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/personal/MyItemsApplication.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.personal; + +import com.arsdigita.web.Application; +import com.arsdigita.persistence.DataObject; + +/** + * Class MyItemsApplication + * + * @author Jon Orris (jorris@arsdigita.com) + * @version $Revision #1 $DateTime: 2004/08/17 23:19:25 $ + */ +public class MyItemsApplication extends Application { + public static final String BASE_DATA_OBJECT_TYPE = + "com.arsdigita.workspace.personal.MyItemsApplication"; + + protected String getBaseDataObjectType() { + return BASE_DATA_OBJECT_TYPE; + } + + // This constructor is used both in creating and retrieving this + // application. + public MyItemsApplication(DataObject dataObject) { + super(dataObject); + } + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/personal/MyItemsResources_en.properties b/ccm-portalserver/src/com/arsdigita/portalserver/personal/MyItemsResources_en.properties new file mode 100644 index 000000000..7228c1c9f --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/personal/MyItemsResources_en.properties @@ -0,0 +1,4 @@ +myitems.controlbar.status=Status +myitems.controlbar.active=Active +myitems.controlbar.incomplete=Incomplete +myitems.controlbar.all=All diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/personal/MyItemsResources_es.properties b/ccm-portalserver/src/com/arsdigita/portalserver/personal/MyItemsResources_es.properties new file mode 100644 index 000000000..140db3831 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/personal/MyItemsResources_es.properties @@ -0,0 +1,4 @@ +myitems.controlbar.status=Estatus +myitems.controlbar.active=Activo +myitems.controlbar.incomplete=Incompleto +myitems.controlbar.all=Todo diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/personal/MyPortalsPortlet.java b/ccm-portalserver/src/com/arsdigita/portalserver/personal/MyPortalsPortlet.java new file mode 100644 index 000000000..77ebd869d --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/personal/MyPortalsPortlet.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.personal; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.web.Application; +import com.arsdigita.portal.apportlet.AppPortlet; +import com.arsdigita.bebop.portal.AbstractPortletRenderer; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.GridPanel; +import com.arsdigita.bebop.PageState; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.DataQuery; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.Party; +import com.arsdigita.util.Assert; +import com.arsdigita.xml.Element; + +public class MyPortalsPortlet extends AppPortlet { + public static final String BASE_DATA_OBJECT_TYPE = + "com.arsdigita.workspace.personal.MyWorkspacesPortlet"; + + protected String getBaseDataObjectType() { + return BASE_DATA_OBJECT_TYPE; + } + + public MyPortalsPortlet(DataObject dataObject) { + super(dataObject); + } + + protected AbstractPortletRenderer doGetPortletRenderer() { + return new MyPortalsPortletRenderer(this); + } + + protected DataQuery getMyPortalsDataQuery(Party party) { + // Assert.assertTrue + Assert.isTrue + (!isNew(), + "You must save this portlet before you call " + + "getMyPortalsDataQuery(User) on it."); + + DataQuery query = SessionManager.getSession().retrieveQuery + ("com.arsdigita.workspace.personal.MyWorkspaces"); + + // Assert.assertNotNull(query, "query"); + Assert.exists(query, "query"); + + query.setParameter("userID", party.getID()); + + Application parent = getParentApplication(); + + // Assert.assertNotNull(parent, "parent"); + Assert.exists(parent, "parent"); + + query.setParameter + ("personalWorkspaceID", getParentApplication().getID()); + + return query; + } +} + +class MyPortalsPortletRenderer extends AbstractPortletRenderer { + private MyPortalsPortlet m_portlet; + + public MyPortalsPortletRenderer(MyPortalsPortlet portlet) { + m_portlet = portlet; + } + + protected void generateBodyXML(PageState pageState, Element parent) { + Party party = Kernel.getContext().getParty(); + + // Assert.assertNotNull(party, "party"); + Assert.exists(party, "party"); + + DataQuery query = m_portlet.getMyPortalsDataQuery(party); + + GridPanel panel = new GridPanel(1); + + String title = null; + String primaryURL = null; + boolean isEmpty = true; + + while (query.next()) { + isEmpty = false; + + // id = query.get("id"); + title = (String) query.get("title"); + primaryURL = (String) query.get("primaryURL"); + + // Assert.assertNotNull(title, "title"); + // Assert.assertNotNull(primaryURL, "primaryURL"); + Assert.exists(title, "title"); + Assert.exists(primaryURL, "primaryURL"); + + panel.add(new Link(title, primaryURL)); + } + + query.close(); + + if (isEmpty) { + panel.add(new Label(GlobalizationUtil.globalize("cw.workspace.personal.none"))); + } + + panel.generateXML(pageState, parent); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/personal/PersonalPortal.java b/ccm-portalserver/src/com/arsdigita/portalserver/personal/PersonalPortal.java new file mode 100644 index 000000000..233a1d249 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/personal/PersonalPortal.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.personal; + +import com.arsdigita.portalserver.PortalSite; +import com.arsdigita.web.Application; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.DataCollection; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.kernel.User; +import com.arsdigita.util.Assert; + +/** + *

    Experimental

    + * + * @author Justin Ross + * @version $Id: PersonalPortal.java pboy $ + */ +public class PersonalPortal extends PortalSite { + + public static final String BASE_DATA_OBJECT_TYPE = + "com.arsdigita.workspace.personal.PersonalWorkspace"; + + protected String getBaseDataObjectType() { + return BASE_DATA_OBJECT_TYPE; + } + + // protected PersonalPortal(DataObject dataObject) { + public PersonalPortal(DataObject dataObject) { + super(dataObject); + } + + public static PersonalPortal createPersonalPortal + (User user, Application parent) { + // Assert.assertNotNull(user, "user"); + Assert.exists(user, "user"); + + PersonalPortal portal = (PersonalPortal) + Application.createApplication + (BASE_DATA_OBJECT_TYPE, user.getID().toString(), + "Personal Portal", parent); + + portal.setOwningUser(user); + + return portal; + } + + public static PersonalPortal createPersonalPortal(User user) { + Application parent = Application.retrieveApplicationForPath + ("/personal-portal/"); + + // Assert.assertNotNull(parent, "parent"); + Assert.exists(parent, "parent"); + + return PersonalPortal.createPersonalPortal(user, parent); + } + + // Can return null. + public static PersonalPortal retrievePersonalPortal(User user) { + DataCollection portals = SessionManager.getSession().retrieve + (BASE_DATA_OBJECT_TYPE); + + portals.addEqualsFilter("user.id", user.getID()); + + PersonalPortal portal = null; + + if (portals.next()) { + portal = (PersonalPortal) Application.retrieveApplication + (portals.getDataObject()); + } + + portals.close(); + + return portal; + } + + private void setOwningUser(User user) { + // Assert.assertNotNull(user, "user"); + Assert.exists(user, "user"); + + setAssociation("user", user); + } + + public User getOwningUser() { + DataObject dataObject = (DataObject) get("user"); + + // Assert.assertNotNull(dataObject, "dataObject"); + Assert.exists(dataObject, "dataObject"); + + return User.retrieve(dataObject); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/personal/PersonalPortalConfig.java b/ccm-portalserver/src/com/arsdigita/portalserver/personal/PersonalPortalConfig.java new file mode 100644 index 000000000..89a70f03c --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/personal/PersonalPortalConfig.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.personal; + +import com.arsdigita.portalserver.PortalTab; +import com.arsdigita.kernel.ResourceType; +import com.arsdigita.kernel.ResourceTypeConfig; +import com.arsdigita.web.Application; +import com.arsdigita.portal.Portlet; +import com.arsdigita.kernel.permissions.PermissionDescriptor; +import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; +import com.arsdigita.util.Assert; + +/** + * XXX Java Doc! + * + * @author Justin Ross + * @version $Id: PersonalPortalConfig.java pboy $ + */ +public class PersonalPortalConfig extends ResourceTypeConfig { + + /** + * Constructor registers itself with ResourceType (map). + */ + public PersonalPortalConfig() { + super(); + + ResourceType.registerResourceTypeConfig + (PersonalPortal.BASE_DATA_OBJECT_TYPE, this); + } + + public void configureApplication(Application application) { + // Assert.assertTrue(application instanceof PersonalPortal); + Assert.isTrue(application instanceof PersonalPortal); + + PersonalPortal portal = (PersonalPortal) application; + + // PortalSite/Portal save ordering is in a disturbing state. + portal.save(); + + // Portlets + + PortalTab tab = PortalTab.createTab("Main"); + + Portlet portlet = null; + + portlet = Portlet.createPortlet + (MyPortalsPortlet.BASE_DATA_OBJECT_TYPE, portal); + tab.addPortlet(portlet, 1); + + tab.setPortalSite(portal); + tab.save(); + + portal.addPortalTab(tab); + portal.addMember(portal.getOwningUser()); + + portal.save(); + + // Permissions + + PermissionDescriptor perm = new PermissionDescriptor + (PrivilegeDescriptor.ADMIN, portal, portal.getOwningUser()); + PermissionService.grantPermission(perm); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/personal/PersonalPortalCreator.java b/ccm-portalserver/src/com/arsdigita/portalserver/personal/PersonalPortalCreator.java new file mode 100644 index 000000000..57cf3bd80 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/personal/PersonalPortalCreator.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.personal; + +import com.arsdigita.web.Application; +import com.arsdigita.persistence.DataObject; + +/** + *

    Experimental

    + * + * This doesn't do anything right now. We would use it if we wanted + * to present the user with an initial configuration UI for creating + * personal portals. + * + * @author Justin Ross + * @version $Id: PersonalPortalCreator.java pboy $ + */ +public class PersonalPortalCreator extends Application { + + public static final String BASE_DATA_OBJECT_TYPE = + "com.arsdigita.workspace.personal.PersonalWorkspaceCreator"; + + protected String getBaseDataObjectType() { + return BASE_DATA_OBJECT_TYPE; + } + +// protected PersonalPortalCreator(DataObject dataObject) { + public PersonalPortalCreator(DataObject dataObject) { + super(dataObject); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/personal/PersonalPortalCreatorDispatcher.java b/ccm-portalserver/src/com/arsdigita/portalserver/personal/PersonalPortalCreatorDispatcher.java new file mode 100644 index 000000000..8d9480c9e --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/personal/PersonalPortalCreatorDispatcher.java @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.personal; + +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.page.PageDispatcher; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.web.Application; +import com.arsdigita.kernel.ResourceTypeConfig; +import com.arsdigita.domain.DataObjectNotFoundException; +import com.arsdigita.dispatcher.Dispatcher; +import com.arsdigita.dispatcher.DispatcherHelper; +import com.arsdigita.dispatcher.RequestContext; +import com.arsdigita.sitenode.SiteNodeRequestContext; +import com.arsdigita.kernel.User; +import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.KernelExcursion; +import com.arsdigita.kernel.SiteNode; +import com.arsdigita.util.Assert; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletException; +import java.io.IOException; +import java.math.BigDecimal; +import org.apache.log4j.Category; + +/** + *

    Experimental

    + * + * @author Justin Ross + * @version $Id: PersonalPortalCreatorDispatcher.java pboy $ + */ +public class PersonalPortalCreatorDispatcher implements Dispatcher { + + private static Category s_log = Category.getInstance + (PersonalPortalCreatorDispatcher.class); + + private Dispatcher m_introDispatcher = null; + + private BigDecimal scanUserID(SiteNodeRequestContext snrc) { + // We expect to get something like "23/" + String url = snrc.getRemainingURLPart(); + + int delimIndex = url.indexOf("/"); + + try { + if (delimIndex == -1) { + return new BigDecimal(url); + } else { + return new BigDecimal(url.substring(0, delimIndex)); + } + } catch (NumberFormatException nfe) { + return null; + } catch (IndexOutOfBoundsException iobe) { + // BigDecimal(String) fails to validate its input. An + // empty string makes it bomb, throwing this exception. + + return null; + } + } + + /** + * Has to be replaced by a way not to use SiteNode / SiteNodeRequestContext + * @param snrc + * @return + */ + private Application getApplication(SiteNodeRequestContext snrc) { + SiteNode siteNode = snrc.getSiteNode(); + + Application parent = Application.retrieveApplicationForSiteNode + (siteNode); + + // Assert.assertNotNull(parent, "parent"); + Assert.exists(parent, "parent"); + + return parent; + } + + private User getUser(BigDecimal userID) { + User user = null; + + try { + user = User.retrieve(userID); + } catch (DataObjectNotFoundException nfe) { + s_log.error + ("Failed to retrieve user " + userID + ".", + new IllegalStateException()); + } + + // Assert.assertNotNull(user, "user"); + Assert.exists(user, "user"); + + return user; + } + + private void configurePortal(PersonalPortal portal) { + ResourceTypeConfig config = + portal.getApplicationType().getConfig(); + + // Assert.assertNotNull(config, "config"); + Assert.exists(config, "config"); + + config.configureResource(portal); + } + + private Page buildIntroPage() { + Page page = new Page("", new SimpleContainer()); + + page.lock(); + + return page; + } + + public void dispatch + (HttpServletRequest request, HttpServletResponse response, + RequestContext context) + throws IOException, ServletException { + // Assert.assertTrue(context instanceof SiteNodeRequestContext); + Assert.isTrue(context instanceof SiteNodeRequestContext); + + // XXX has to be replaced by a way NOT built upon SiteNode* + SiteNodeRequestContext snrc = (SiteNodeRequestContext) context; + + final Application parent = getApplication(snrc); + + BigDecimal userID = scanUserID(snrc); + + if (userID == null) { + s_log.warn + ("Failed to read a user ID from a personal-portal link."); + } else { + final User user = getUser(userID); + + PersonalPortal portal = + PersonalPortal.retrievePersonalPortal(user); + + if (portal == null) { + // This is what we expect to happen. + KernelExcursion rootExcursion = new KernelExcursion() { + protected void excurse() { + setParty(Kernel.getSystemParty()); + PersonalPortal ps = + PersonalPortal.createPersonalPortal (user, parent); + + // Assert.assertNotNull(ps, "portal"); + Assert.exists(ps, "portal"); + + configurePortal(ps); + + ps.save(); + }}; + rootExcursion.run(); + } else { + // There's a problem. We should never get here if the + // portal already exists, since the site node + // dispatcher will go to an existing portal + // directly, skipping this dispatcher. + + s_log.error + ("PersonalPortalCreator invoked when the portalsite " + + "exists already.", new IllegalStateException()); + } + + // Not synchronized, since it makes little difference. + + if (m_introDispatcher == null) { + m_introDispatcher = new PageDispatcher(buildIntroPage()); + } + + // Assert.assertNotNull(m_introDispatcher, "m_introDispatcher"); + Assert.exists(m_introDispatcher, "m_introDispatcher"); + + DispatcherHelper.sendRedirect + (request, response, snrc.getOriginalURL()); + + // The following does not work because I need to be able to + // reset the RequestContext before I invoke it. Otherwise, + // the remainingURL is incorrect. + //DispatcherHelper.forwardRequestByPath + // (snrc.getOriginalURL(), request, response); + } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/personal/PersonalPortalDispatcher.java b/ccm-portalserver/src/com/arsdigita/portalserver/personal/PersonalPortalDispatcher.java new file mode 100644 index 000000000..bd41faff7 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/personal/PersonalPortalDispatcher.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.personal; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.bebop.DimensionalNavbar; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.page.PageDispatcher; +import com.arsdigita.dispatcher.Dispatcher; +import com.arsdigita.dispatcher.RequestContext; + +import com.arsdigita.portalserver.ui.admin.PortalAdminPage; +import com.arsdigita.portalserver.ui.PortalDispatcher; +import com.arsdigita.portalserver.ui.PortalParticipants; + +import java.util.Map; +import java.util.HashMap; +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletException; + +/** + *

    Experimental

    + * + * @author Justin Ross + * @version $Id: //portalserver/dev/src/com/arsdigita/portalserver/personal/PersonalPortalDispatcher.java#5 $ + */ +public class PersonalPortalDispatcher extends PortalDispatcher { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/personal/PersonalPortalDispatcher.java#5 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private Dispatcher m_portalAdminDispatcher; + + public PersonalPortalDispatcher() { + super(); + + Map m = new HashMap(); + + m.put("", new PersonalPortalHomePage()); + m.put(PORTAL_PARTICIPANT_PAGE, PortalParticipants.createPage()); + + setMap(m); + } + + @Override + public void dispatch(HttpServletRequest request, + HttpServletResponse response, + RequestContext context) + throws IOException, ServletException { + String remainingURLPart = context.getRemainingURLPart(); + + if (remainingURLPart.startsWith(PORTAL_ADMIN_PAGE)) { + if (m_portalAdminDispatcher == null) { + PortalAdminPage page = new PortalAdminPage() { + protected void buildContextBar() { + DimensionalNavbar navbar = new DimensionalNavbar(); + + navbar.setClassAttr("portalNavbar"); + + navbar.add + (new Link(new PersonalPortalLinkPrinter())); + navbar.add(new Label(GlobalizationUtil.globalize("cw.workspace.personal.configure_workspace"))); + + getHeader().add(navbar); + } + }; + + m_portalAdminDispatcher = new PageDispatcher(page); + } + + m_portalAdminDispatcher.dispatch(request, response, context); + } else { + super.dispatch(request, response, context); + } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/personal/PersonalPortalHomePage.java b/ccm-portalserver/src/com/arsdigita/portalserver/personal/PersonalPortalHomePage.java new file mode 100644 index 000000000..b952542ae --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/personal/PersonalPortalHomePage.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.personal; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.portalserver.PortalSite; +import com.arsdigita.portalserver.ui.PortalHomePage; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.DimensionalNavbar; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.bebop.event.PrintEvent; +import com.arsdigita.kernel.User; +import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.permissions.UniversalPermissionDescriptor; +import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; +import com.arsdigita.util.Assert; +import com.arsdigita.bebop.Container; + +/** + *

    Experimental

    + * + * @author Justin Ross + * @version $Id: //portalserver/dev/src/com/arsdigita/portalserver/personal/PersonalPortalHomePage.java#8 $ + */ +public class PersonalPortalHomePage extends PortalHomePage { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/personal/PersonalPortalHomePage.java#8 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private final RequestLocal m_adminPermission = new RequestLocal() { + protected Object initialValue(PageState state) { + UniversalPermissionDescriptor descriptor = + new UniversalPermissionDescriptor + (PrivilegeDescriptor.ADMIN, + Kernel.getContext().getParty()); + + if (PermissionService.checkPermission(descriptor)) { + return Boolean.TRUE; + } else { + return Boolean.FALSE; + } + } + }; + + public PersonalPortalHomePage() { + super(); + } + + protected void buildHeader(Container header) { + // Add a link to edit profile. + Link profileLink = new Link( new Label(GlobalizationUtil.globalize("cw.workspace.personal.edit_your_profile")), "/register/edit-profile"); + profileLink.setClassAttr("portalControlProfileLink"); + header.add(profileLink); + + // And to change passwords. + Link passwordLink = new Link( new Label(GlobalizationUtil.globalize("cw.workspace.personal.change_your_password")), "/register/change-password"); + passwordLink.setClassAttr("portalControlProfileLink"); + header.add(passwordLink); + + // If the user is an administrator, offer her a link to + // the Portal admin page. + + Link adminLink = new Link( new Label(GlobalizationUtil.globalize("cw.workspace.personal.site_administration")), "/portal-admin/") { + public boolean isVisible(PageState state) { + Boolean bool = (Boolean) m_adminPermission.get(state); + return bool.booleanValue(); + } + }; + + adminLink.setClassAttr("portalControlProfileLink"); + header.add(adminLink); + + super.buildHeader(header); + } + + protected void buildTitle() { + class TitlePrintListener implements PrintListener { + public void prepare(PrintEvent e) { + PageState pageState = e.getPageState(); + + PortalSite psite = PortalSite.getCurrentPortalSite + (pageState.getRequest()); + + // Assert.assertTrue(psite instanceof PersonalPortal); + Assert.isTrue(psite instanceof PersonalPortal); + + PersonalPortal pp = (PersonalPortal) psite; + + User user = pp.getOwningUser(); + + String givenName = user.getPersonName().getGivenName(); + + Label target = (Label) e.getTarget(); + + if (givenName.endsWith("s")) { + target.setLabel(givenName + "' " + pp.getTitle()); + } else { + target.setLabel(givenName + "'s " + pp.getTitle()); + } + + // That was notably english only. + } + } + + setTitle(new Label(new TitlePrintListener())); + } + + protected void buildContextBar() { + DimensionalNavbar navbar = new DimensionalNavbar(); + + navbar.add(new Label(GlobalizationUtil.globalize("cw.workspace.personal.personal_workspace"))); + navbar.setClassAttr("portalNavbar"); + + getHeader().add(navbar); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/pslogin/PSPage.java b/ccm-portalserver/src/com/arsdigita/portalserver/pslogin/PSPage.java new file mode 100644 index 000000000..ed7a0fc68 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/pslogin/PSPage.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.pslogin; + +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.event.RequestEvent; +import com.arsdigita.bebop.event.RequestListener; +import com.arsdigita.dispatcher.DispatcherHelper; +import com.arsdigita.domain.DataObjectNotFoundException; +import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.KernelExcursion; +import com.arsdigita.kernel.Party; +import com.arsdigita.kernel.User; +import com.arsdigita.kernel.security.Initializer; +import com.arsdigita.util.Assert; +import com.arsdigita.kernel.ResourceTypeConfig; +import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.kernel.permissions.PermissionDescriptor; +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; +import com.arsdigita.portalserver.PortalSite; +import com.arsdigita.portalserver.personal.PersonalPortal; + +// ///////////////////////////////////////////////////////////////////////////// +// +// Has to be refactored! +// Uses methods in c.ad.kernel.security.Initializer which have been modified +// and moved to ui +// +// CURRENTLY NOT WORKING +// +// ///////////////////////////////////////////////////////////////////////////// + +/** + * This Page redirects a user to his personal portal. + * It sets up that portal if it has not been initialized + * @author Bryan Che + **/ +public class PSPage extends Page { + + //constructor + public PSPage() { + addRequestListener(new PSPageRequestListener()); + lock(); + } +} + +class PSPageRequestListener implements RequestListener { + + public void pageRequested(RequestEvent e) { + User user; + String sUrl = ""; + Party party = Kernel.getContext().getParty(); + if (party == null) { + // URL f. login Page neuerdings über web.ui..... + // sUrl = Initializer.getURL(Initializer.LOGIN_PAGE_KEY); + } else { + try { + user = User.retrieve(party.getOID()); + + // Get the user's personal portal + PortalSite psite = PersonalPortal. + retrievePersonalPortal(user); + if (psite == null) { + psite = setupPersonalPortal(user); + } + + sUrl = psite.getPrimaryURL(); + + } catch ( DataObjectNotFoundException donfe ) { + // sUrl = Initializer.getURL(Initializer.LOGIN_PAGE_KEY); + } + + } + + // Redirect to the user's portal (or login) + try { + DispatcherHelper.sendRedirect(e.getPageState().getRequest(), + e.getPageState().getResponse(), + sUrl); + } catch (java.io.IOException ioe) { + //this method can't throw an exception in this Interface, so ignore + } + } + + //borrow the code for setting up a personal portal from + //com.arsdigita.portalserver.personal.PersonalPortalCreatorDispatcher + private PortalSite setupPersonalPortal(final User u) { + final PortalSite[] m_psite = new PortalSite[] { null }; + + KernelExcursion rootExcursion = new KernelExcursion() { + public void excurse() { + setParty(Kernel.getSystemParty()); + + PersonalPortal psite = PersonalPortal. + createPersonalPortal(u); + // Assert.assertNotNull(psite, "workspace"); + Assert.exists(psite, "workspace"); + ResourceTypeConfig config = psite. + getApplicationType().getConfig(); + // Assert.assertNotNull(config, "config"); + Assert.exists(config, "config"); + + config.configureResource(psite); + psite.save(); + PermissionService.grantPermission + (new PermissionDescriptor + (PrivilegeDescriptor.ADMIN, psite, u)); + + m_psite[0] = psite; + }}; + + rootExcursion.run(); + + return m_psite[0]; + + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/pslogin/PSSubsiteDispatcher.java b/ccm-portalserver/src/com/arsdigita/portalserver/pslogin/PSSubsiteDispatcher.java new file mode 100644 index 000000000..11535920f --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/pslogin/PSSubsiteDispatcher.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.pslogin; + +import com.arsdigita.ui.login.SubsiteDispatcher; +import com.arsdigita.kernel.security.Initializer; +import com.arsdigita.bebop.Page; +import java.util.Map; + +// ///////////////////////////////////////////////////////////////////////////// +// +// Has to be refactored! +// Uses methods in c.ad.kernel.security.Initializer which have been modified +// and moved to ui +// +// CURRENTLY NOT WORKING +// +// ///////////////////////////////////////////////////////////////////////////// + + +/** + * This class extends com.arsdigita.ui.login.SubsiteDispatcher + * It changes the subsite dispatcher behavior by + * directing logged-in users to a personal portal + * rather than the default system portal + * @author Bryan Che + **/ +public class PSSubsiteDispatcher extends SubsiteDispatcher { + + private static Page s_psPage = new PSPage(); + + /** + * Initializes dispatcher by registering URLs with bebop pages. + * Replaces the portal mapping from an ACS workspace + * to a portalserver portal + **/ + public PSSubsiteDispatcher() { + super(); + + Map map = this.getMap(); + //override the default ACS workspace page + //with a personal portal page + + // Funktioniert so nicht mehr, weil es die map in den alten + // kernel.security.initializer nicht mehr gibt. + // !! put(map, Initializer.WORKSPACE_PAGE_KEY, s_psPage); + + + setMap(map); + } + + /** + * Adds to the given map, where URL is looked up from the + * page map using the given key. If the URL represents a directory + * (ends with "/"), URL+"index" is also added to the map and URL-"/" is + * redirected to URL. + **/ + private void put(Map map, String key, Page page) { + //!! String url = Initializer.getURL(key); + // map.put(url, page); + // if (url.endsWith("/")) { + // map.put(url+"index", page); + // requireTrailingSlash(url.substring(0, url.length()-1)); + // } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/ParticipantBrowsePane.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/ParticipantBrowsePane.java new file mode 100644 index 000000000..10c3eb8e5 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/ParticipantBrowsePane.java @@ -0,0 +1,519 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import java.io.IOException; +import java.math.BigDecimal; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Iterator; + +import com.arsdigita.portalserver.*; +import com.arsdigita.portalserver.Role; +import com.arsdigita.portalserver.RoleCollection; + +import com.arsdigita.web.RedirectSignal; + +import com.arsdigita.bebop.*; +import com.arsdigita.bebop.event.*; +import com.arsdigita.bebop.form.*; +import com.arsdigita.kernel.*; +import com.arsdigita.kernel.permissions.*; + +import com.arsdigita.bebop.list.AbstractListModelBuilder; +import com.arsdigita.bebop.list.ListModel; +import com.arsdigita.bebop.parameters.StringParameter; + +import com.arsdigita.kernel.ui.ACSObjectSelectionModel; +import com.arsdigita.toolbox.ui.PrivilegedComponentSelector; +import com.arsdigita.toolbox.ui.IteratorListModel; +import com.arsdigita.persistence.OID; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.domain.DataObjectNotFoundException; + + +import com.arsdigita.util.UncheckedWrapperException; +import org.apache.log4j.Category; + +public class ParticipantBrowsePane { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/ParticipantBrowsePane.java#8 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static Category s_log = Category.getInstance + (ParticipantBrowsePane.class.getName()); + + private ParticipantBrowsePane() { + // No construction. + } + + public static Component createForUser + (final RequestLocal portalsite, + final StringParameter actionParam, + final ActionListener selectSearch) { + return buildBrowsePane(portalsite, actionParam, selectSearch, + false); + } + + public static Component createForAdmin + (final RequestLocal portalsite, + final StringParameter actionParam, + final ActionListener selectSearch) { + return buildBrowsePane(portalsite, actionParam, selectSearch, + true); + } + + private static Component buildBrowsePane + (final RequestLocal portalsiteRL, + final StringParameter actionParam, + final ActionListener selectBrowse, + final boolean isAdmin) { + final ACSObjectSelectionModel selectionModel = + new ACSObjectSelectionModel("selectedparticipant"); + + final List participantList = new List(); + participantList.setSelectionModel(selectionModel); + participantList.setEmptyView(new Label("")); + + final List initialsList = new List() { + public boolean isVisible(PageState ps) { + PortalSite psite = (PortalSite) portalsiteRL.get(ps); + return (psite.getParticipantCount() > 20) && super.isVisible(ps); + } + }; + initialsList.setLayout(List.HORIZONTAL); + initialsList.setEmptyView(new Label(GlobalizationUtil.globalize("cw.workspace.ui.no_participants"))); + initialsList.setModelBuilder(new AbstractListModelBuilder() { + public ListModel makeModel(List l, PageState ps) { + PortalSite psite = (PortalSite) portalsiteRL.get(ps); + return new IteratorListModel(psite.getParticipantInitials()); + } + }); + final RequestLocal firstInitialRL = new RequestLocal() { + public Object initialValue(PageState ps) { + PortalSite psite = (PortalSite) portalsiteRL.get(ps); + Iterator initials = psite.getParticipantInitials(); + if (!initials.hasNext()) { + return null; + } + return initials.next(); + } + }; + initialsList.setSelectionModel( + new ParameterSingleSelectionModel(new StringParameter("initial")) { + public Object getSelectedKey(PageState ps) { + if (!initialsList.isVisible(ps)) { + return null; + } + Object result = super.getSelectedKey(ps); + if (result != null) { + return result; + } + return firstInitialRL.get(ps); + } + public boolean isSelected(PageState ps) { + if (!initialsList.isVisible(ps)) { + return false; + } + Object result = super.getSelectedKey(ps); + if (result != null) { + return true; + } + return (firstInitialRL.get(ps) != null); + } + }); + initialsList.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent ev) { + PageState ps = ev.getPageState(); + ps.reset(participantList); + } + }); + + participantList.setModelBuilder(new AbstractListModelBuilder() { + public ListModel makeModel(List l, PageState ps) { + PortalSite psite = (PortalSite) portalsiteRL.get(ps); + String initial = (String) initialsList.getSelectedKey(ps); + + if (initial == null) { + return new ParticipantListModel(psite); + } else { + return new ParticipantListModel(psite, initial); + } + } + }); + + final DynamicListWizard dlw = + new DynamicListWizard + ("Portal Participants", participantList, + selectionModel, "Add a participant", + new Label("")) { + public void register(Page p) { + super.register(p); + + if (!isAdmin) { + p.setVisibleDefault(getListLabel(), false); + p.setVisibleDefault(getAddLink(), false); + } + + final DynamicListWizard theDLW = this; + + p.addRequestListener(new RequestListener() { + public void pageRequested(RequestEvent ev) { + PageState ps = ev.getPageState(); + + String action = (String) ps.getValue(actionParam); + + if (action == null + || !action.startsWith("browse")) { + return; + } + + BigDecimal partyID = new BigDecimal + (action.substring(6)); + + ps.setValue(actionParam, null); + + selectBrowse.actionPerformed + (new ActionEvent(theDLW, ps)); + + OID partyOID = new OID + (ACSObject.BASE_DATA_OBJECT_TYPE, partyID); + + Party party; + + try { + party = (Party) + DomainObjectFactory.newInstance(partyOID); + } catch (DataObjectNotFoundException ex) { + return; + } + + String initial; + + if (party instanceof User) { + initial = ((User) party).getPersonName() + .getFamilyName() + .substring(0, 1) + .toUpperCase(); + } else { + initial = ((Group) party).getName() + .substring(0, 1) + .toUpperCase(); + } + + initialsList.setSelectedKey(ps, initial); + participantList.setSelectedKey + (ps, partyID.toString()); + } + }); + } + }; + dlw.setHeader(initialsList); + + RequestLocal participantRL = new RequestLocal() { + public Object initialValue(PageState ps) { + return selectionModel.getSelectedObject(ps); + } + }; + + ActionListener onDelete = new ActionListener() { + public void actionPerformed(ActionEvent ev) { + dlw.reset(ev.getPageState()); + } + }; + + Component participantEdit = new ParticipantEdit + (portalsiteRL, participantRL, onDelete); + + Component participantDisplay = new ParticipantDisplay + (portalsiteRL, participantRL); + + final Component participantEditOrDisplay = + new PrivilegedComponentSelector(PrivilegeDescriptor.ADMIN, + portalsiteRL, + participantEdit, + participantDisplay); + dlw.setEditPane(participantEditOrDisplay); + + // This change listener ensures that we don't get an edit pane + // or add pane in some weird intermediate state + selectionModel.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent ev) { + ev.getPageState().reset(participantEditOrDisplay); + } + }); + + if (isAdmin) { + dlw.setAddPane(buildAddParticipant(portalsiteRL)); + } + + return dlw; + } + + private static FormSection buildRoleFormSection + (final RequestLocal portalsiteRL, final RequestLocal participantRL) { + FormSection form = new FormSection(new ColumnPanel(1)); + + Label rHeader = new Label(GlobalizationUtil.globalize("cw.workspace.ui.roles")); + rHeader.setFontWeight(Label.BOLD); + form.add(rHeader); + final CheckboxGroup roles = new CheckboxGroup("roles"); + roles.setPrintListener(new PrintListener() { + public void prepare(PrintEvent ev) { + CheckboxGroup tgt = (CheckboxGroup)ev.getTarget(); + PageState ps = ev.getPageState(); + PortalSite psite = (PortalSite)portalsiteRL.get(ps); + RoleCollection roleColl = psite.getRoles(); + while (roleColl.next()) { + tgt.addOption(new Option(roleColl.getID().toString(), + roleColl.getRoleName())); + } + } + }); + + form.add(roles); + + form.addInitListener(new FormInitListener() { + public void init(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + + Party party = (Party)participantRL.get(ps); + if (party == null) { + return; + } + + PortalSite psite = (PortalSite)portalsiteRL.get(ps); + + RoleCollection rc = psite.getRoles(); + LinkedList roleIDs = new LinkedList(); + while (rc.next()) { + Role r = rc.getRole(); + if (r.hasDirectMemberOrSubgroup(party)) { + roleIDs.add(rc.getID().toString()); + } + } + roles.setValue(ps, roleIDs.toArray()); + } + }); + + form.addProcessListener(new FormProcessListener() { + public void process(final FormSectionEvent ev) { + PageState ps = ev.getPageState(); + + Object[] roleIDstrs = (Object[])roles.getValue(ps); + final HashSet roleIDs = new HashSet(); + if (roleIDstrs != null) { + int i; + for (i = 0; i < roleIDstrs.length; i++) { + BigDecimal id + = new BigDecimal((String)roleIDstrs[i]); + roleIDs.add(id); + Role role = (Role) DomainObjectFactory.newInstance + (new OID(Role.BASE_DATA_OBJECT_TYPE, id)); + role.getPortalSite().assertPrivilege + (PrivilegeDescriptor.ADMIN); + } + } + + KernelExcursion ex = new KernelExcursion() { + protected void excurse() { + setEffectiveParty(Kernel.getSystemParty()); + doProcess(roleIDs, ev.getPageState()); + } + }; + ex.run(); + } + + private void doProcess(HashSet roleIDs, PageState ps) { + Party party = (Party)participantRL.get(ps); + RoleCollection rc = ((PortalSite)portalsiteRL.get(ps)).getRoles(); + + while (rc.next()) { + Role role = rc.getRole(); + if (roleIDs.contains(role.getID())) { + if (!role.hasDirectMemberOrSubgroup(party)) { + role.addMemberOrSubgroup(party); + role.save(); + } + } else { + if (role.hasDirectMemberOrSubgroup(party)) { + role.removeMemberOrSubgroup(party); + role.save(); + } + } + } + } + }); + + return form; + } + + private static Component buildAddParticipant + (final RequestLocal portalsiteRL) { + final RequestLocal partiesRL = new RequestLocal(); + + final Form userSearch = new Form("usersearch"); + userSearch.setMethod(Form.POST); + + final Label searchRedoLabel = new Label(""); + final Label emptyLabel = new Label(""); + + final Form userAdd = + new Form("useradd", new BoxPanel(BoxPanel.VERTICAL)); + userAdd.setMethod(Form.POST); + + final Container result = new SimpleContainer(); + result.add(userSearch); + final ModalContainer bottomHalf = new ModalContainer(); + bottomHalf.add(emptyLabel); + bottomHalf.add(searchRedoLabel); + bottomHalf.add(userAdd); + bottomHalf.setDefaultComponent(emptyLabel); + result.add(bottomHalf); + + userSearch.add( + new Label(GlobalizationUtil.globalize("cw.workspace.ui.enter_first_name_last_name_andor_email_address"))); + final TextField query = new TextField("query"); + userSearch.add(query); + userSearch.add(new Label("")); + userSearch.add(new Submit("Search")); + userSearch.add(new Label()); + userSearch.add(new FormErrorDisplay(userSearch), + ColumnPanel.FULL_WIDTH); + + userSearch.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent e) + throws FormProcessException { + PageState ps = e.getPageState(); + + + PortalSite psite = (PortalSite)portalsiteRL.get(ps); + + PartyCollection parties = psite.getNonParticipants(); + parties.filter((String) query.getValue(ps)); + + long count = parties.size(); + if (count == 0) { + bottomHalf.setVisibleComponent(ps, searchRedoLabel); + searchRedoLabel.setLabel( (String) GlobalizationUtil.globalize("cw.workspace.ui.no_matches_found").localize() , ps); + } else if (count > 100) { + bottomHalf.setVisibleComponent(ps, searchRedoLabel); + searchRedoLabel.setLabel( + count + " matches found. Please enter more" + + " specific search criteria.", ps); + } else { + partiesRL.set(ps, parties); + bottomHalf.setVisibleComponent(ps, userAdd); + } + } + }); + + userAdd.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.select_user_or_group_to_add"))); + final RadioGroup users = new RadioGroup("users"); + users.setLayout(RadioGroup.VERTICAL); + + userAdd.add(users); + + final RequestLocal addedParticipantRL = new RequestLocal() { + public Object initialValue(PageState ps) { + String partIDstr = (String)users.getValue(ps); + if (partIDstr == null) { + return null; + } + OID partyOID = new OID(ACSObject.BASE_DATA_OBJECT_TYPE, + new BigDecimal(partIDstr)); + try { + return (Party) DomainObjectFactory.newInstance(partyOID); + } catch (DataObjectNotFoundException ex) { + return null; + } + } + }; + + //userAdd.add(buildRoleFormSection(portalsiteRL, addedParticipantRL)); + + userAdd.add(new Submit("Add Participant")); + + userAdd.addInitListener(new FormInitListener() { + public void init(FormSectionEvent e) { + PageState ps = e.getPageState(); + PartyCollection parties = (PartyCollection) partiesRL.get(ps); + if (parties == null) { + // This is not a pleasing way to fix this. I + // don't understand the logic requiring an illegal + // state exception to be thrown here. + bottomHalf.setVisibleComponent(ps, emptyLabel); + return; + //throw new IllegalStateException("partiesRL not set"); + } + if (parties.next()) { + do { + EmailAddress email = parties.getPrimaryEmail(); + users.addOption( + new Option(parties.getID().toString(), + parties.getDisplayName() + + (email == null ? "" : + " <" + email.getEmailAddress() + ">")), + ps); + } while (parties.next()); + } else { + // XXX deal with no users case + users.addOption(new Option("none", "No Users Found"), ps); + } + } + }); + + userAdd.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent e) + throws FormProcessException { + PageState ps = e.getPageState(); + + final PortalSite psite = (PortalSite) portalsiteRL.get(ps); + final Party party = (Party) addedParticipantRL.get(ps); + + psite.assertPrivilege(PrivilegeDescriptor.ADMIN); + KernelExcursion ex = new KernelExcursion() { + protected void excurse() { + setEffectiveParty(Kernel.getSystemParty()); + psite.addParticipant(party); + psite.save(); + } + }; + ex.run(); + + ps.reset(result); + String url = null; + + try { + url = ps.stateAsURL(); + } catch (IOException ioe) { + throw new UncheckedWrapperException(ioe); + } + + throw new RedirectSignal(url, true); + } + }); + + return result; + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/ParticipantEdit.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/ParticipantEdit.java new file mode 100644 index 000000000..8c021ce2b --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/ParticipantEdit.java @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import java.math.BigDecimal; +import java.util.Iterator; + +import com.arsdigita.portalserver.*; +import com.arsdigita.portalserver.Role; +import com.arsdigita.portalserver.RoleCollection; + +import com.arsdigita.bebop.*; +import com.arsdigita.bebop.event.*; +import com.arsdigita.bebop.form.*; +import com.arsdigita.kernel.*; +import com.arsdigita.kernel.permissions.*; + +import com.arsdigita.bebop.list.ListModel; +import com.arsdigita.bebop.table.AbstractTableModelBuilder; +import com.arsdigita.bebop.table.TableModel; +import com.arsdigita.bebop.table.DefaultTableCellRenderer; +import com.arsdigita.bebop.table.TableColumn; + +import com.arsdigita.toolbox.ui.IteratorListModel; +import com.arsdigita.domain.DomainCollectionIterator; +import com.arsdigita.domain.DataObjectNotFoundException; + +import com.arsdigita.portalserver.permissions.PartyPermissionEdit; + +import org.apache.log4j.Category; + +/** + * + * + * @author Justin Ross <jross@redhat.com> + */ +public class ParticipantEdit extends CompoundComponent { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/ParticipantEdit.java#6 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static Category s_log = Category.getInstance + (ParticipantEdit.class.getName()); + + private static final IteratorListModel.KeyFunction s_keyFunc = + new IteratorListModel.KeyFunction() { + public String getKey(Object obj) { + return ((Role)obj).getID().toString(); + } + }; + + public ParticipantEdit(final Container container, + final RequestLocal portalsiteRL, + final RequestLocal participantRL, + final ActionListener onDelete) { + super(container); + ((BoxPanel) container).setWidth("100%"); + + Label header = new Label(GlobalizationUtil.globalize("cw.workspace.ui.participant_info")); + header.setFontWeight(Label.BOLD); + + add(header); + add(new PropertySheet(new PropertySheetModelBuilder() { + public void lock() { + /* Do nothing. */ + } + + public boolean isLocked() { + return container.isLocked(); + } + + public PropertySheetModel makeModel(PropertySheet sheet, + final PageState ps) { + return new ParticipantModel((Party) participantRL.get(ps), + (PortalSite) portalsiteRL.get(ps), + false); + } + })); + + add(new Label("")); + + Label roleHeader = new Label(GlobalizationUtil.globalize("cw.workspace.ui.participant_roles")); + roleHeader.setFontWeight(Label.BOLD); + add(roleHeader); + + final String GRANT = "grant"; + final String REVOKE = "revoke"; + final Table roleEdit = new Table() { + public void respond(PageState ps) { + String eventName = ps.getControlEventName(); + if (!GRANT.equals(eventName) && !REVOKE.equals(eventName)) { + throw new IllegalStateException("Unknown event name"); + } + BigDecimal roleID = + new BigDecimal(ps.getControlEventValue()); + Party participant = (Party)participantRL.get(ps); + Role role; + try { + role = new Role(roleID); + } catch (DataObjectNotFoundException ex) { + throw new IllegalStateException("Unknown role ID"); + } + if (GRANT.equals(eventName)) { + if (!role.hasDirectMemberOrSubgroup(participant)) { + role.addMemberOrSubgroup(participant); + role.save(); + } + } else { + if (role.hasDirectMemberOrSubgroup(participant)) { + role.removeMemberOrSubgroup(participant); + role.save(); + } + } + } + }; + roleEdit.setHeader(null); + roleEdit.getColumnModel().add(new TableColumn(0)); + roleEdit.getColumnModel().add(new TableColumn(1)); + roleEdit.getColumnModel().add(new TableColumn(2)); + roleEdit.setClassAttr("plain"); + roleEdit.setModelBuilder(new AbstractTableModelBuilder() { + public TableModel makeModel(Table t, PageState ps) { + PortalSite psite = (PortalSite)portalsiteRL.get(ps); + RoleCollection rc = psite.getRoles(); + // This chain of adapters is either sick or + // beautiful. I'm not sure which. + Iterator roleIter = new DomainCollectionIterator(rc); + ListModel roleLM = + new IteratorListModel(roleIter, s_keyFunc); + return new GridTableModel(roleLM, 3); + } + }); + + final Label emptyLabel = new Label(""); + final RequestLocal dynamicLabel = new RequestLocal() { + public Object initialValue(PageState ps) { + return new Label(); + } + }; + final RequestLocal eventValueRL = new RequestLocal(); + final RequestLocal grantDisplay = new RequestLocal() { + public Object initialValue(PageState state) { + SimpleContainer result = new SimpleContainer(); + result.add(new ControlLink(Icons.CHECK_EMPTY_16) { + public void setControlEvent(PageState ps) { + ps.setControlEvent(roleEdit, GRANT, + (String)eventValueRL.get(ps)); + } + }); + + result.add((Component)dynamicLabel.get(state)); + return result; + } + }; + final RequestLocal revokeDisplay = new RequestLocal() { + public Object initialValue(PageState state) { + SimpleContainer result = new SimpleContainer(); + result.add(new ControlLink(Icons.CHECK_FULL_16) { + public void setControlEvent(PageState ps) { + ps.setControlEvent(roleEdit, + REVOKE, + (String)eventValueRL.get(ps)); + } + }); + + result.add((Component)dynamicLabel.get(state)); + return result; + } + }; + roleEdit.setDefaultCellRenderer(new DefaultTableCellRenderer() { + public Component getComponent(Table t, PageState ps, + Object value, boolean isSelected, + Object key, int row, int col) { + if (value == null) { + return emptyLabel; + } + Party participant = (Party)participantRL.get(ps); + Role role = (Role)value; + + if (value != null) { + eventValueRL.set(ps, role.getID().toString()); + Label l = (Label)dynamicLabel.get(ps); + l.setLabel(role.getRoleName()); + if (role.hasDirectMemberOrSubgroup(participant)) { + return (Component)revokeDisplay.get(ps); + } else { + return (Component)grantDisplay.get(ps); + } + } else { + return emptyLabel; + } + } + }); + add(roleEdit); + + add(new PartyPermissionEdit("Additional Privileges", + portalsiteRL, + participantRL)); + + final ActionLink removeParticipant = new ActionLink( + "Remove this participant from this portal"); + removeParticipant.setClassAttr("actionLink"); + removeParticipant.setConfirmation( + "Really remove participant from Portal?"); + removeParticipant.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + final PageState ps = e.getPageState(); + final PortalSite psite = (PortalSite) portalsiteRL.get(ps); + final Party p = (Party) participantRL.get(ps); + psite.assertPrivilege(PrivilegeDescriptor.ADMIN); + KernelExcursion ex = new KernelExcursion() { + protected void excurse() { + setEffectiveParty(Kernel.getSystemParty()); + psite.removeParticipant(p); + psite.save(); + } + }; + ex.run(); + onDelete.actionPerformed + (new ActionEvent(ParticipantEdit.this, ps)); + } + }); + add(removeParticipant); + } + + public ParticipantEdit(final RequestLocal portalsiteRL, + final RequestLocal participantRL, + final ActionListener onDelete) { + this(new BoxPanel(BoxPanel.VERTICAL), + portalsiteRL, + participantRL, + onDelete); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/ParticipantSearchPane.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/ParticipantSearchPane.java new file mode 100644 index 000000000..c302d68d2 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/ParticipantSearchPane.java @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + + +import com.arsdigita.portalserver.*; + +import com.arsdigita.bebop.*; +import com.arsdigita.bebop.event.*; +import com.arsdigita.bebop.form.*; +import com.arsdigita.kernel.*; +import com.arsdigita.kernel.permissions.*; + +import com.arsdigita.bebop.list.AbstractListModelBuilder; +import com.arsdigita.bebop.list.ListModel; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.bebop.parameters.NotEmptyValidationListener; + +import com.arsdigita.kernel.ui.ACSObjectSelectionModel; +import com.arsdigita.toolbox.ui.ACSObjectCollectionListModel; +import com.arsdigita.toolbox.ui.PrivilegedComponentSelector; + + +import org.apache.log4j.Category; + +/** + * + * + * @author Justin Ross (jross@redhat.com) + */ +public class ParticipantSearchPane { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/ParticipantSearchPane.java#5 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static Category s_log = Category.getInstance + (ParticipantSearchPane.class.getName()); + + private ParticipantSearchPane() { + // No construction. + } + + public static Component create(final RequestLocal portalsite, + final StringParameter actionParam, + final ActionListener selectSearch) { + return buildSearchPane(portalsite, actionParam, selectSearch); + } + + private static + Component buildSearchPane(final RequestLocal portalsiteRL, + final StringParameter actionParam, + final ActionListener selectSearch) { + final ACSObjectSelectionModel selectionModel = + new ACSObjectSelectionModel("selectedparticipant"); + + + final StringParameter searchString = + new StringParameter("searchString"); + + final List participantList = new List(); + participantList.setSelectionModel(selectionModel); + + final Label emptyView = new Label(""); + participantList.setEmptyView(emptyView); + + participantList.setModelBuilder(new AbstractListModelBuilder() { + public ListModel makeModel(List l, PageState ps) { + String searchStringValue = (String) ps.getValue(searchString); + if (searchStringValue == null || searchStringValue.equals("")) { + return new ListModel() { + public boolean next() { return false; } + public Object getElement() { return null; } + public String getKey() { return null; } + }; + } else { + PortalSite psite = (PortalSite)portalsiteRL.get(ps); + PartyCollection pc = psite.getParticipants(); + pc.filter(searchStringValue); + long count = pc.size(); + if (count < 100 && count > 0) { + return new ACSObjectCollectionListModel(pc); + } else { + if (count == 0) { + emptyView.setLabel( (String) GlobalizationUtil.globalize("cw.workspace.ui.no_matches_found").localize() , ps); + } else { + emptyView.setLabel( + count + " matches found. Please enter more" + + " specific search criteria.", ps); + } + return new ListModel() { + public boolean next() { return false; } + public Object getElement() { return null; } + public String getKey() { return null; } + }; + } + } + } + }); + + final DynamicListWizard dlw = new DynamicListWizard + ("Participants", participantList, selectionModel, "", + new Label("")) { + public void register(Page p) { + super.register(p); + p.addComponentStateParam(this, searchString); + p.setVisibleDefault(getListLabel(), false); + p.setVisibleDefault(getAddLink(), false); + } + }; + + final Form searchForm = new Form("participantSearch", + new ColumnPanel(1)); + + Label searchLabel = new Label(GlobalizationUtil.globalize("cw.workspace.ui.enter_search_criteria")); + searchLabel.setFontWeight(Label.BOLD); + searchForm.add(searchLabel); + + final TextField searchStringEntry = new TextField("searchEntry"); + searchStringEntry.addValidationListener( + new NotEmptyValidationListener("No search criteria entered")); + searchForm.add(searchStringEntry); + searchForm.add(new Submit("Search")); + + searchForm.addInitListener(new FormInitListener() { + public void init(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + String searchStringValue = (String)ps.getValue(searchString); + if (searchStringValue == null) { + return; + } + searchStringEntry.setValue(ps, searchStringValue); + } + }); + + searchForm.addSubmissionListener(new FormSubmissionListener() { + public void submitted(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + ps.reset(participantList); + ps.setValue(searchString, null); + } + }); + + searchForm.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + ps.setValue(searchString, searchStringEntry.getValue(ps)); + } + }); + + dlw.setHeader(searchForm); + + RequestLocal participantRL = new RequestLocal() { + public Object initialValue(PageState ps) { + return selectionModel.getSelectedObject(ps); + } + }; + + Component participantEdit = new ParticipantEdit + (portalsiteRL, + participantRL, + new ActionListener() { + public void actionPerformed(ActionEvent e) { + dlw.reset(e.getPageState()); + } + }); + + Component participantDisplay = + new ParticipantDisplay(portalsiteRL, participantRL); + + final Component participantEditOrDisplay = + new PrivilegedComponentSelector(PrivilegeDescriptor.ADMIN, + portalsiteRL, + participantEdit, + participantDisplay); + dlw.setEditPane(participantEditOrDisplay); + + // This change listener ensures that we don't get an edit pane + // or add pane in some weird intermediate state + selectionModel.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent ev) { + ev.getPageState().reset(participantEditOrDisplay); + } + }); + + return dlw; + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/PortalDispatcher.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/PortalDispatcher.java new file mode 100644 index 000000000..7d2ba08d7 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/PortalDispatcher.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui; + +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.page.PageDispatcher; +import com.arsdigita.bebop.page.BebopMapDispatcher; +import com.arsdigita.portalserver.ui.admin.PortalAdminPage; +import com.arsdigita.dispatcher.Dispatcher; +import com.arsdigita.dispatcher.RequestContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletException; +import java.util.Map; +import java.util.HashMap; +import java.io.IOException; +import org.apache.log4j.Logger; + +/** + *

    Experimental

    + * + * @author Justin Ross + * @version $Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/PortalDispatcher.java#5 $ + */ +public class PortalDispatcher extends BebopMapDispatcher { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/PortalDispatcher.java#5 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static final Logger s_log = Logger.getLogger + (PortalDispatcher.class); + + // XXX Move these to constant pool. + + protected static final String PORTAL_HOME_PAGE = "index.xhtml"; + protected static final String PORTAL_ADMIN_PAGE = "admin"; + protected static final String PORTAL_PARTICIPANT_PAGE = "participants"; + + private Dispatcher m_portalsiteAdminDispatcher; + + public PortalDispatcher() { + super(); + + Page portalHomePage = new PortalHomePage(); + + Map m = new HashMap(); + m.put("", portalHomePage); + m.put(PORTAL_HOME_PAGE, portalHomePage); + m.put(PORTAL_PARTICIPANT_PAGE, PortalParticipants.createPage()); + setMap(m); + } + + public void dispatch(HttpServletRequest request, + HttpServletResponse response, + RequestContext context) + throws IOException, ServletException { + String remainingURLPart = context.getRemainingURLPart(); + + + if (s_log.isDebugEnabled()) { + s_log.debug("Remaining URL part is '" + remainingURLPart + "'"); + } + + if (remainingURLPart.startsWith(PORTAL_ADMIN_PAGE)) { + if (m_portalsiteAdminDispatcher == null) { + m_portalsiteAdminDispatcher = + new PageDispatcher(new PortalAdminPage()); + } + + m_portalsiteAdminDispatcher.dispatch(request, response, context); + } else { + super.dispatch(request, response, context); + } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/PortalHomePage.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/PortalHomePage.java new file mode 100644 index 000000000..d8142c219 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/PortalHomePage.java @@ -0,0 +1,392 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.web.ApplicationCollection; +import com.arsdigita.portalserver.PortalSite; +import com.arsdigita.portalserver.LoggedInLinkWrapper; +import com.arsdigita.portalserver.PortalPage; +import com.arsdigita.portalserver.PortalTab; +import com.arsdigita.portalserver.PortalTabCollection; + +import com.arsdigita.bebop.Container; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.List; +import com.arsdigita.bebop.list.ListCellRenderer; +import com.arsdigita.bebop.list.ListModelBuilder; +import com.arsdigita.bebop.list.ListModel; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.DimensionalNavbar; +import com.arsdigita.bebop.event.RequestListener; +import com.arsdigita.bebop.event.RequestEvent; +import com.arsdigita.bebop.event.ChangeListener; +import com.arsdigita.bebop.event.ChangeEvent; +import com.arsdigita.bebop.portal.Portal; +import com.arsdigita.bebop.portal.PortalModel; +import com.arsdigita.bebop.portal.PortalModelBuilder; +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; +import com.arsdigita.portal.DefaultPortalModel; +import com.arsdigita.util.Assert; +import com.arsdigita.xml.Element; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.Cookie; +import org.apache.log4j.Logger; + +/** + * + * @author Justin Ross + * @author Jim Parsons + * @version $Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/PortalHomePage.java#7 $ + */ +public class PortalHomePage extends PortalPage { + private static final Cookie[] EMPTY_COOKIES = {}; + + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/PortalHomePage.java#7 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static final Logger s_log = Logger.getLogger + (PortalHomePage.class); + + public static final String PORTAL_XML_NS = + "http://www.arsdigita.com/portalserver/1.0"; + + List m_tabs; + + private RequestLocal m_hasAdmin = new RequestLocal() { + public Object initialValue(PageState ps) { + PortalSite psite = + PortalSite.getCurrentPortalSite(ps.getRequest()); + if (psite.checkPrivilege(PrivilegeDescriptor.ADMIN)) { + return Boolean.TRUE; + } else { + return Boolean.FALSE; + } + } + }; + + public PortalHomePage() { + super(); + + addRequestListener(new PortalRequestListener()); + + lock(); + } + + private boolean hasAdmin(PageState ps) { + return m_hasAdmin.get(ps).equals(Boolean.TRUE); + } + + // Can return null. + protected PortalSite getPortalSite(PageState pageState) { + return PortalSite.getCurrentPortalSite(pageState.getRequest()); + } + + protected void buildContextBar() { + DimensionalNavbar navbar = new DimensionalNavbar(); + + navbar.setClassAttr("portalNavbar"); + + navbar.add(new LoggedInLinkWrapper(new PersonalPortalLinkPrinter())); + navbar.add(new Label(new CurrentPortalLabelPrinter())); + + getHeader().add(navbar); + } + + protected void buildHeader(Container header) { + Link adminLink = new Link( new Label(GlobalizationUtil.globalize("cw.workspace.ui.configure_workspace")), "./admin") { + public boolean isVisible(PageState ps) { + return hasAdmin(ps); + } + }; + adminLink.setClassAttr("portalControl"); + + header.add(adminLink); + + class SearchComponent extends SimpleContainer { + public void generateXML(PageState state, Element parent) { +/*XXXjbp - ************************************************* + ****This needs to be modified to use core search*********** + + Element elem = new Element + ("km:search", KmConstants.KM_XML_NS); + + PortalSite portalsite = PortalSite.getCurrentPortalSite + (state.getRequest()); + + ApplicationCollection apps = + portalsite.getChildApplicationsForType + (KnowledgeManager.BASE_DATA_OBJECT_TYPE); + + if (apps.next()) { + elem.addAttribute + ("url", apps.getPrimaryURL() + "search.jsp"); + } else { + elem.addAttribute + ("url", "#"); + } + + apps.close(); + + exportAttributes(elem); + + parent.addContent(elem); +*/ + } + } + + header.add(new SearchComponent()); + } + + protected void buildBody(Container body) { + ListModelBuilder lmb = new ListModelBuilder() { + boolean m_isLocked; + + public ListModel makeModel(List l, PageState pageState) { + return new TabsListModel(pageState); + } + + public void lock() { + m_isLocked = true; + } + + public boolean isLocked() { + return m_isLocked; + } + }; + + m_tabs = new List(lmb); + + m_tabs.setClassAttr("portalTabs"); + + m_tabs.setCellRenderer(new TabsListCellRenderer()); + + m_tabs.addChangeListener(new CookieChangeListener()); + + body.add(m_tabs); + } + + /* + protected void buildContextBar() { + DimensionalNavbar navbar = new DimensionalNavbar(); + + // To generate a link to the user's personal portal. + class PWLinkPrintListener implements PrintListener { + public void prepare(PrintEvent e) { + Link link = (Link) e.getTarget(); + PageState pageState = e.getPageState(); + + KernelRequestContext krc = + KernelHelper.getKernelRequestContext + (pageState.getRequest()); + + UserContext uc = krc.getUserContext(); + + link.setTarget("/personal-portal/" + uc.getUserID() + "/"); + } + } + + navbar.add(new Link( new Label(GlobalizationUtil.globalize("cw.workspace.ui.personal_workspace")), new PWLinkPrintListener())); + navbar.add(new Label(new TitlePrintListener())); + navbar.setClassAttr("portalNavbar"); + + setContextBar(navbar); + } + */ + + private class PortalRequestListener implements RequestListener { + + + public void pageRequested(RequestEvent e) { + + PageState ps = e.getPageState(); + boolean notFound = true; + PortalSite portalsite = getPortalSite(ps); + + // Assert.assertNotNull(portalsite, "workspace"); + Assert.exists(portalsite, "workspace"); + + if (!portalsite.isReady()) { + // ad_script_abort + } + + //if no tab is selected, check cookies + if (!m_tabs.isSelected(ps)) { + String prtlID = portalsite.getID().toString(); + + // form cookie name val by concatenating 'prtl_' + portal ID + String cookiePRTLName = "prtl_" + prtlID; + + HttpServletRequest httpRequest = ps.getRequest(); + + // get cookie array + Cookie[] cookies = getCookies(httpRequest); + + // If name val exists, get value + String result = getCookieValue(cookies, cookiePRTLName); + + // check if this tab ID is still present in this portal + TabsListModel tlm = new TabsListModel(ps); + if (result != null) { + while (tlm.next()) { + String tmpstr = tlm.getKey(); + if (result.equals(tmpstr)) { + m_tabs.setSelectedKey(ps,tmpstr); + notFound = false; + break; + } + } + if (notFound) { + //use the first tab in the collection as the + //one to display... + tlm.reset(); + + if (tlm.next()) { + String key = tlm.getKey(); + m_tabs.setSelectedKey(ps,key); + } + } + } else { + if (tlm.next()) { + String key = tlm.getKey(); + m_tabs.setSelectedKey(ps,key); + } + } + + tlm.close(); + } + } + + // Wraps getCookies on request, since it doesn't follow the + // sane java convention of returning an empty array, + // but instead returns null; + private Cookie[] getCookies(HttpServletRequest httpRequest) { + Cookie[] cookies = httpRequest.getCookies(); + if (cookies == null) { + return EMPTY_COOKIES; + } + return cookies; + } + + public String getCookieValue(Cookie[] cookies, String cookieName) { + for (int i=0; i < cookies.length; i++) { + Cookie cookie = cookies[i]; + if (cookieName.equals(cookie.getName())) { + return (cookie.getValue()); + } + } + return null; + } + + } + + private class TabsListModel implements ListModel { + PortalTabCollection ptabs = null; + PortalTab ptab = null; + + TabsListModel(PageState pageState) { + PortalSite psite = getPortalSite(pageState); + ptabs = psite.getTabsForPortalSite(); + } + + public boolean next() { + return ptabs.next(); + } + + public Object getElement() { + return ptabs.getPortalTab(); + } + + public String getKey() { + return ptabs.getID().toString(); + } + + public void close() { + ptabs.close(); + } + + public void reset() { + ptabs.rewind(); + } + } //end TabsListModel + + class TabsListCellRenderer implements ListCellRenderer { + public Component getComponent + (List list, PageState pageState, Object value, String key, + int index, boolean isSelected) + { + PortalTab ptab = (PortalTab) value; + + if (isSelected) { + String layout = ptab.getLayout(); + com.arsdigita.bebop.portal.Portal port = + new com.arsdigita.bebop.portal.Portal + (new PortalTabsModelBuilder(ptab)); + port.setStyleAttr(layout.toUpperCase()); + return port; + } else { + return new ControlLink(ptab.getTitle()); + } + } + } //end cell renderer + + class PortalTabsModelBuilder implements PortalModelBuilder { + PortalTab m_ptab; + + PortalTabsModelBuilder(PortalTab ptab) { + m_ptab = ptab; + } + + public PortalModel buildModel(PageState pageState) { + //Change to defaultTab model... + return new DefaultPortalModel(m_ptab); + } + } + + private class CookieChangeListener implements ChangeListener { + public void stateChanged(ChangeEvent e) { + PageState ps = e.getPageState(); + PortalSite psite = getPortalSite(ps); + + // Assert.assertNotNull(psite, "workspace"); + Assert.exists(psite, "workspace"); + + HttpServletResponse response = ps.getResponse(); + String cookieNameString = "prtl_" + psite.getID().toString(); + String tabName = (String)m_tabs.getSelectedKey(ps); + Cookie cookie = new Cookie(cookieNameString,tabName); + cookie.setMaxAge(36000); + cookie.setComment( + "This cookie returns you to the tab you " + + "had open when you last visited this portal." + ); + response.addCookie(cookie); + } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/PortalParticipants.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/PortalParticipants.java new file mode 100644 index 000000000..73776a94e --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/PortalParticipants.java @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + + +import com.arsdigita.portalserver.*; +import com.arsdigita.portalserver.Role; +import com.arsdigita.portalserver.RoleCollection; +import com.arsdigita.portalserver.personal.PersonalPortal; + +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.bebop.*; +import com.arsdigita.bebop.event.*; +import com.arsdigita.bebop.form.*; +import com.arsdigita.kernel.*; +import com.arsdigita.kernel.permissions.*; + +import com.arsdigita.bebop.list.ListModel; +import com.arsdigita.bebop.parameters.StringParameter; + + + +import org.apache.log4j.Category; + +public class PortalParticipants { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/PortalParticipants.java#5 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static Category s_log = Category.getInstance + (PortalParticipants.class.getName()); + + private PortalParticipants() { + // No construction. + } + + public static PortalPage createPage() { + final RequestLocal portalsiteRL = new RequestLocal() { + public Object initialValue(PageState ps) { + return PortalSite.getCurrentPortalSite(ps.getRequest()); + } + }; + + PortalPage p = new ParticipantPortalPage(); + + final StringParameter actionParam = new StringParameter("action"); + p.addGlobalStateParam(actionParam); + + p.setTitle(new Label(new PrintListener() { + public void prepare(PrintEvent ev) { + Label tgt = (Label) ev.getTarget(); + PortalSite psite = + (PortalSite) portalsiteRL.get(ev.getPageState()); + tgt.setLabel(psite.getTitle() + " Participants"); + } + })); + + final TabbedPane mainDisplay = new TabbedPane(); + + Component browsePane = ParticipantBrowsePane.createForUser + (portalsiteRL, actionParam, new ActionListener() { + public void actionPerformed(ActionEvent ev) { + mainDisplay.setSelectedIndex(ev.getPageState(), 0); + } + }); + mainDisplay.addTab("Browse", browsePane); + + Component searchPane = ParticipantSearchPane.create + (portalsiteRL, actionParam, new ActionListener() { + public void actionPerformed(ActionEvent ev) { + mainDisplay.setSelectedIndex(ev.getPageState(), 1); + } + }); + + mainDisplay.addTab("Search", searchPane); + + p.add(mainDisplay); + + p.addRequestListener(new RequestListener() { + public void pageRequested(RequestEvent ev) { + PageState ps = ev.getPageState(); + String actionName = (String) ps.getValue(actionParam); + + if (actionName != null) { + if (actionName.equals("search")) { + mainDisplay.setSelectedIndex(ps, 1); + ps.setValue(actionParam, null); + } + } + } + }); + + p.lock(); + + return p; + } +} + +class ParticipantPortalPage extends PortalPage { + protected void buildContextBar() { + DimensionalNavbar navbar = new DimensionalNavbar(); + + navbar.setClassAttr("portalNavbar"); + + navbar.add(new Link(new PersonalPortalLinkPrinter())); + + // This link will not show up if the current portal is a + // personal portal. + Link current = new Link(new CurrentPortalLinkPrinter()) { + public boolean isVisible(PageState state) { + PortalSite psite = PortalSite.getCurrentPortalSite + (state.getRequest()); + + return !(psite instanceof PersonalPortal); + } + }; + navbar.add(current); + + navbar.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.participants"))); + + getHeader().add(navbar); + } +} + +class ParticipantListModel implements ListModel { + protected PartyCollection m_p; + + public ParticipantListModel(PortalSite p, String initial) { + m_p = p.getParticipantsWithInitial(initial); + } + + public ParticipantListModel(PortalSite p) { + m_p = p.getParticipants(); + } + + public boolean next() { + if (m_p.next()) { + return true; + } else { + return false; + } + } + + public Object getElement() { + return m_p.getDisplayName(); + } + + public String getKey() { + return m_p.getID().toString(); + } +} + +class ParticipantDisplay extends CompoundComponent { + public ParticipantDisplay(Container container, + final RequestLocal portalsiteRL, + final RequestLocal participantRL) { + super(container); + + Label header = new Label(GlobalizationUtil.globalize("cw.workspace.ui.participant_info")); + header.setFontWeight(Label.BOLD); + add(header); + + add(new PropertySheet(new PropertySheetModelBuilder() { + public void lock() { + // Do nothing. + } + + public boolean isLocked() { + return ParticipantDisplay.this.isLocked(); + } + + public PropertySheetModel makeModel(PropertySheet sheet, + final PageState ps) { + return new ParticipantModel((Party) participantRL.get(ps), + (PortalSite) portalsiteRL.get(ps), true); + } + })); + } + + public ParticipantDisplay(final RequestLocal portalsiteRL, + final RequestLocal participantRL) { + this(new BoxPanel(BoxPanel.VERTICAL), portalsiteRL, participantRL); + } +} + +class ParticipantModel implements PropertySheetModel { + int m_counter = -1; + Party m_p; + PortalSite m_psite; + boolean m_includeRoles; + + ParticipantModel(Party p, PortalSite psite, boolean includeRoles) { + m_p = p; + m_psite = psite; + m_includeRoles = includeRoles; + } + + public boolean nextRow() { + if ((m_includeRoles && (m_counter == 2)) || + (!m_includeRoles && (m_counter == 1))) { + return false; + } + m_counter++; + return true; + } + + /** + * @deprecated use getGlobalizedLabel instead + */ + public String getLabel() { + return getGlobalizedLabel().getKey(); + } + + public GlobalizedMessage getGlobalizedLabel() { + if (m_counter == 0) { + return GlobalizationUtil.globalize("cw.workspace.ui.email"); + } else if (m_counter == 1) { + return GlobalizationUtil.globalize("cw.workspace.ui.name"); + } else if (m_counter == 2) { + return GlobalizationUtil.globalize("cw.workspace.ui.roles"); + } else { + throw new IllegalStateException("invalid counter"); + } + } + + public String getValue() { + if (m_counter == 0) { + if (m_p.getPrimaryEmail() != null) { + return m_p.getPrimaryEmail().getEmailAddress(); + } else { + return "None"; + } + } else if (m_counter == 1) { + return m_p.getDisplayName(); + } else if (m_counter == 2) { + StringBuffer result = new StringBuffer(); + boolean foundFirst = false; + RoleCollection rc = m_psite.getRoles(); + while (rc.next()) { + Role r = rc.getRole(); + // XXX: determining role membership + if (r.hasDirectMemberOrSubgroup(m_p)) { + if (foundFirst) { + result.append(", "); + } + result.append(r.getAssigneeTitle()); + foundFirst = true; + } + } + return result.toString(); + } else { + throw new IllegalStateException("invalid counter"); + } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/ApplicationCreateComponent.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/ApplicationCreateComponent.java new file mode 100644 index 000000000..6baa25618 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/ApplicationCreateComponent.java @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + + +import java.math.BigDecimal; + +import java.util.HashMap; + +import com.arsdigita.xml.Element; + +import com.arsdigita.bebop.BoxPanel; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.CompoundComponent; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.GridPanel; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; + +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; + +import com.arsdigita.bebop.form.Submit; + + +import com.arsdigita.kernel.ui.ResourceConfigFormSection; +import com.arsdigita.web.ApplicationType; +import com.arsdigita.kernel.ResourceType; +import com.arsdigita.web.ApplicationTypeCollection; +import com.arsdigita.portal.PortletType; +import com.arsdigita.portal.PortletTypeCollection; + +import org.apache.log4j.Logger; + +/** + * @version $Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/admin/ApplicationCreateComponent.java#5 $ + */ +public class ApplicationCreateComponent extends CompoundComponent { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/admin/ApplicationCreateComponent.java#5 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static final Logger s_log = Logger.getLogger + (ApplicationCreateComponent.class); + + private RequestLocal m_appTypeRL; + + private HashMap m_configureComponents; + + public interface Builder { + public Component build(ResourceConfigFormSection acfs); + } + + public static class DefaultBuilder implements Builder { + private final ActionListener m_onSuccess; + private final ActionListener m_onCancel; + + public DefaultBuilder(ActionListener onSuccess, + ActionListener onCancel) { + m_onSuccess = onSuccess; + m_onCancel = onCancel; + } + + public Component build(final ResourceConfigFormSection acfs) { + final Form f = new Form("ac", new GridPanel(1)); + f.add(acfs); + BoxPanel buttons = new BoxPanel(BoxPanel.HORIZONTAL); + final Submit create = new Submit("Create"); + final Submit cancel = new Submit("Cancel"); + buttons.add(create); + buttons.add(cancel); + f.add(buttons); + // XXX: label on create button + f.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) + throws FormProcessException { + PageState ps = ev.getPageState(); + if (create.isSelected(ps)) { + acfs.createResource(ps).save(); + m_onSuccess.actionPerformed(new ActionEvent(f, ps)); + } else if (cancel.isSelected(ps)) { + m_onCancel.actionPerformed(new ActionEvent(f, ps)); + } + } + }); + + return f; + } + } + + public ApplicationCreateComponent(RequestLocal appTypeRL, + RequestLocal parentApplicationRL, + boolean forPortlets, + ActionListener onSuccess, + ActionListener onCancel) { + this(appTypeRL, parentApplicationRL, forPortlets, + new DefaultBuilder(onSuccess, onCancel)); + } + + public ApplicationCreateComponent(RequestLocal appTypeRL, + RequestLocal parentApplicationRL, + boolean forPortlets, + Builder builder) { + m_appTypeRL = appTypeRL; + + m_configureComponents = new HashMap(); + + if (forPortlets) { + s_log.debug("Building a portlet create component"); + + PortletTypeCollection types = + PortletType.retrieveAllPortletTypes(); + + while (types.next()) { + PortletType type = types.getPortletType(); + + ResourceConfigFormSection config = type.getCreateFormSection + (parentApplicationRL); + + // XXX LOOKY - This incorrectly returns a BasicResourceConfigFormSection: + // + // DEBUG admin.ApplicationCreateComponent - Fetched + // config + // com.arsdigita.kernel.ui.BasicResourceConfigFormSection@78a2af6a + // for type 'Knowledge Items' with ID 155 + + if (s_log.isDebugEnabled()) { + s_log.debug("Fetched config " + config + " for type '" + + type.getTitle() + "' with ID " + type.getID()); + } + + if (config != null) { + Component c = builder.build(config); + m_configureComponents.put(type.getID(), c); + add(c); + } + } + } else { + s_log.debug("Building an application create component"); + + ApplicationTypeCollection types = + ApplicationType.retrieveAllApplicationTypes(); + + while (types.next()) { + ApplicationType type = types.getApplicationType(); + + ResourceConfigFormSection config = + type.getCreateFormSection(parentApplicationRL); + + if (s_log.isDebugEnabled()) { + s_log.debug("Fetched config " + config + " for type '" + + type.getTitle() + "'"); + } + + if (config != null) { + Component c = builder.build(config); + m_configureComponents.put(type.getID(), c); + add(c); + } + } + } + } + + public Component get(PageState ps) { + ResourceType rt = (ResourceType) m_appTypeRL.get(ps); + + if (!canCreate(rt)) { + throw new IllegalStateException("can not display form for a: " + + rt.getTitle()); + } + + return (Component) m_configureComponents.get(rt.getID()); + } + + public void generateXML(PageState ps, Element parentElt) { + Component c = get(ps); + + if (s_log.isDebugEnabled()) { + s_log.debug("Generating XML of component " + c + " fetched " + + "using ID " + ((ResourceType) m_appTypeRL.get(ps)).getID()); + } + + c.generateXML(ps, parentElt); + } + + public boolean canCreate(BigDecimal appTypeID) { + return m_configureComponents.containsKey(appTypeID); + } + + public boolean canCreate(ResourceType rt) { + return m_configureComponents.containsKey(rt.getID()); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/ApplicationModifyComponent.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/ApplicationModifyComponent.java new file mode 100644 index 000000000..51e5e9064 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/ApplicationModifyComponent.java @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + + +import java.math.BigDecimal; + +import java.util.HashMap; + +import com.arsdigita.xml.Element; + +import com.arsdigita.bebop.BoxPanel; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.CompoundComponent; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.GridPanel; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; + +import com.arsdigita.kernel.Resource; +import com.arsdigita.kernel.ui.ResourceConfigFormSection; +import com.arsdigita.web.ApplicationType; +import com.arsdigita.kernel.ResourceType; +import com.arsdigita.kernel.Resource; +import com.arsdigita.web.ApplicationTypeCollection; +import com.arsdigita.kernel.ResourceTypeCollection; +import com.arsdigita.portal.PortletType; +import com.arsdigita.portal.PortletTypeCollection; + +public class ApplicationModifyComponent extends CompoundComponent { + private RequestLocal m_appRL; + + private HashMap m_configureComponents; + + public interface Builder { + public Component build(ResourceConfigFormSection acfs); + } + + public static class DefaultBuilder implements Builder { + private final RequestLocal m_appRL; + private final ActionListener m_onSuccess; + private final ActionListener m_onCancel; + + public DefaultBuilder(RequestLocal appRL, + ActionListener onSuccess, + ActionListener onCancel) { + m_appRL = appRL; + m_onSuccess = onSuccess; + m_onCancel = onCancel; + } + + public Component build(final ResourceConfigFormSection acfs) { + final Form f = new Form("ac", new GridPanel(1)); + f.add(acfs); + BoxPanel buttons = new BoxPanel(BoxPanel.HORIZONTAL); + final Submit update = new Submit("Update"); + final Submit cancel = new Submit("Cancel"); + buttons.add(update); + buttons.add(cancel); + f.add(buttons); + // XXX: label on update button + f.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + if (update.isSelected(ps)) { + acfs.modifyResource(ps); + ((Resource) m_appRL.get(ps)).save(); + m_onSuccess.actionPerformed(new ActionEvent(f, ps)); + } else if (cancel.isSelected(ps)) { + m_onCancel.actionPerformed(new ActionEvent(f, ps)); + } + } + }); + + return f; + } + } + + public ApplicationModifyComponent(final RequestLocal appRL, + boolean forPortlets, + final ActionListener onSuccess, + final ActionListener onCancel) { + this(appRL, forPortlets, new DefaultBuilder(appRL, + onSuccess, + onCancel)); + } + + public ApplicationModifyComponent(RequestLocal appRL, + boolean forPortlets, + Builder builder) { + m_appRL = appRL; + + m_configureComponents = new HashMap(); + ResourceTypeCollection atc; + if (forPortlets) { + atc = PortletType.retrieveAllPortletTypes(); + } else { + atc = ApplicationType.retrieveAllApplicationTypes(); + } + while (atc.next()) { + ResourceType at; + if (forPortlets) { + at = (PortletType)((PortletTypeCollection)atc).getPortletType(); + } else { + at = (ApplicationType)((ApplicationTypeCollection)atc).getApplicationType(); + } + ResourceConfigFormSection fs = at.getModifyFormSection(m_appRL); + + if (fs != null) { + Component c = builder.build(fs); + m_configureComponents.put(at.getID(), c); + add(c); + } + } + } + + public Component get(PageState ps) { + ResourceType type = ((Resource) m_appRL.get(ps)).getResourceType(); + + if (!canModify(type.getID())) { + throw new IllegalStateException + ("Cannot display form for a " + type.getTitle()); + } + + return (Component) m_configureComponents.get(type.getID()); + } + + public void generateXML(PageState ps, Element parentElt) { + get(ps).generateXML(ps, parentElt); + } + + boolean canModify(BigDecimal resTypeID) { + return m_configureComponents.containsKey(resTypeID); + } + + boolean canModify(ResourceType rt) { + return m_configureComponents.containsKey(rt.getID()); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/ApplicationsPane.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/ApplicationsPane.java new file mode 100644 index 000000000..3906c2c7a --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/ApplicationsPane.java @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import java.math.BigDecimal; + +import com.arsdigita.bebop.AbstractSingleSelectionModel; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.ComponentSelectionModel; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.GridPanel; +import com.arsdigita.bebop.Image; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.ModalContainer; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.SimpleComponent; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.SplitWizard; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.bebop.parameters.ParameterModel; +import com.arsdigita.web.Application; +import com.arsdigita.web.ApplicationCollection; +import com.arsdigita.kernel.ui.ResourceConfigFormSection; +import com.arsdigita.web.ApplicationType; +import com.arsdigita.web.ApplicationTypeCollection; +import com.arsdigita.portalserver.PortalSite; +import com.arsdigita.portalserver.PortalPage; +import com.arsdigita.portal.Portlet; +import com.arsdigita.xml.Element; +import javax.servlet.ServletException; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; +import org.apache.log4j.Logger; + +/** + * Experimental + * + * @author Justin Ross + * @version $Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/admin/ApplicationsPane.java#7 $ + */ +public final class ApplicationsPane { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/admin/ApplicationsPane.java#7 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static final Logger s_log = + Logger.getLogger(ApplicationsPane.class.getName()); + + private ApplicationsPane() { } // To prevent construction. + + public static Component create(final RequestLocal portalsiteRL) { + final BigDecimalParameter appTypeParam = new BigDecimalParameter("at"); + final SplitWizard sw = new SplitWizard + (new Label("Please select an application type from the " + + "list on the left.")) { + public void respond(PageState ps) + throws javax.servlet.ServletException { + String name = ps.getControlEventName(); + String value = ps.getControlEventValue(); + + if ("apptype".equals(name)) { + ps.setValue(appTypeParam, new BigDecimal(value)); + } else { + super.respond(ps); + } + } + + public void register(Page p) { + super.register(p); + p.addComponentStateParam(this, appTypeParam); + } + }; + + GridPanel appTypePanel = new GridPanel(1); + ApplicationTypeCollection atc = + ApplicationType.retrieveAllApplicationTypes(); + atc.filterToFullPageViewable(); + atc.filterToWorkspaceApplication(); + atc.orderByTitle(); + + Map map = new HashMap(); + while (atc.next()) { + final BigDecimal id = atc.getID(); + + appTypePanel.add(new ControlLink(atc.getTitle()) { + public void setControlEvent(PageState ps) { + ps.setControlEvent(sw, "apptype", id.toString()); + } + }); + + ApplicationType appType = atc.getApplicationType(); + appType.disconnect(); + Component c = editView(portalsiteRL, appType, true); + sw.add(c); + map.put(atc.getID(), c); + } + + SimpleContainer leftPanel = new SimpleContainer(); + Label header = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.tool_type")); + header.setFontWeight(Label.BOLD); + leftPanel.add(header); + leftPanel.add(appTypePanel); + + sw.setSelector(leftPanel); + sw.setSelectionModel(new MapComponentSelector(map, appTypeParam)); + + return sw; + } + + private static class MapComponentSelector + extends AbstractSingleSelectionModel + implements ComponentSelectionModel { + + private Map m_componentMap; + private ParameterModel m_model; + + MapComponentSelector(Map componentMap, ParameterModel model) { + m_componentMap = componentMap; + m_model = model; + } + + public Object getSelectedKey(PageState ps) { + return ps.getValue(m_model); + } + + public void setSelectedKey(PageState ps, Object key) { + ps.setValue(m_model, key); + } + + public Component getComponent(PageState ps) { + return (Component) m_componentMap.get(getSelectedKey(ps)); + } + + public ParameterModel getStateParameter() { return m_model; } + } + + static Component editView(final RequestLocal portalsiteRL, + final ApplicationType type, + boolean fullPagePortal) { + + // app or portlet + final BigDecimalParameter selectedParam = + new BigDecimalParameter("sp"); + + final ModalContainer container = new ModalContainer() { + public void register(Page p) { + super.register(p); + p.addComponentStateParam(this, selectedParam); + } + }; + + final ActionListener reset = new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + ps.reset(container); + ((PortalPage) ps.getPage()).goUnmodal(ps); + container.setVisible(ps, true); + } + }; + + final RequestLocal selectedPortletRL = new RequestLocal() { + protected Object initialValue(PageState ps) { + BigDecimal portletID = + (BigDecimal) ps.getValue(selectedParam); + if (portletID == null) { + return null; + } + return Portlet.retrievePortlet(portletID); + } + }; + + final Component portletModifyComponent = + new ApplicationModifyComponent(selectedPortletRL, true, + reset, reset); + + final RequestLocal selectedAppRL = new RequestLocal() { + protected Object initialValue(PageState ps) { + BigDecimal appID = + (BigDecimal) ps.getValue(selectedParam); + if (appID == null) { + return null; + } + return Application.retrieveApplication(appID); + } + }; + + ResourceConfigFormSection appModify = + type.getModifyFormSection(selectedAppRL); + + final Component appModifyForm = + new ApplicationModifyComponent.DefaultBuilder + (selectedAppRL, reset, reset).build(appModify); + + final ResourceConfigFormSection appCreate = + type.getCreateFormSection(portalsiteRL); + + final Component appCreateForm = + new ApplicationCreateComponent.DefaultBuilder + (reset, reset).build(appCreate); + + final Component appsDisplay = + new ApplicationsDisplay(portalsiteRL, type, fullPagePortal) { + public void respond(PageState ps) throws ServletException { + String name = ps.getControlEventName(); + String value = ps.getControlEventValue(); + if (ApplicationsDisplay.CREATE.equals(name)) { + ((PortalPage) ps.getPage()).goModal(ps, appCreateForm); + } else if (ApplicationsDisplay.CONFIG_PORTLET.equals(name)) { + ((PortalPage)ps.getPage()).goModal(ps, portletModifyComponent); + ps.setValue(selectedParam, new BigDecimal(value)); + } else if (ApplicationsDisplay.CONFIG_APP.equals(name)) { + ((PortalPage) ps.getPage()).goModal(ps, appModifyForm); + ps.setValue(selectedParam, new BigDecimal(value)); + } else { + super.respond(ps); + } + } + }; + + container.add(appsDisplay); + container.add(appCreateForm); + container.add(portletModifyComponent); + container.add(appModifyForm); + container.setDefaultComponent(appsDisplay); + + return container; + } + + private static class ApplicationsDisplay extends SimpleComponent { + static final String CREATE = "c"; + static final String CONFIG_PORTLET = "cp"; + static final String CONFIG_APP = "ca"; + + private RequestLocal m_portalsiteRL; + + private ControlLink m_confLink; + private Label m_linkLabel; + private ControlLink m_link; + private ApplicationType m_appType; + private boolean m_fullPagePortal; + + ApplicationsDisplay(RequestLocal portalsiteRL, ApplicationType type, + boolean fullPagePortal) { + m_portalsiteRL = portalsiteRL; + m_linkLabel = new Label(""); + m_link = new ControlLink(m_linkLabel); + Image i = new Image("/assets/general/Edit16.gif"); + i.setBorder("0"); + m_confLink = new ControlLink(i); + m_appType = type; + m_fullPagePortal = fullPagePortal; + } + + public void generateXML(PageState ps, Element parent) { + PortalSite psite = (PortalSite) m_portalsiteRL.get(ps); + parent = parent.newChildElement("portalserver:appsDisplay", + PortalPage.PORTAL_XML_NS); + + parent.addAttribute("name", m_appType.getTitle()); + + ApplicationCollection apps; + + if (m_fullPagePortal) { + apps = psite.getFullPagePortalSiteApplications(); + } else { + apps = psite.getChildApplications(); + } + + apps.filterToApplicationType(m_appType.getApplicationObjectType()); + apps.orderByTitle(); + + String currentObjectType = ""; + + if (!m_appType.isSingleton() || apps.size() == 0) { + m_linkLabel.setLabel( (String) GlobalizationUtil.globalize("cw.workspace.ui.admin.create_new").localize() + " " + m_appType.getTitle(), ps); + ps.setControlEvent(this, ApplicationsDisplay.CREATE, ""); + m_link.setClassAttr("actionLink"); + m_link.generateXML(ps, parent); + } + + while (apps.next()) { + Element appElt = + parent.newChildElement("portalserver:appsDisplayApp", + PortalPage.PORTAL_XML_NS); + + m_linkLabel.setLabel(apps.getTitle(), ps); + new Link(m_linkLabel, apps.getPrimaryURL()).generateXML( ps, appElt); + + Element descr = + appElt.newChildElement("portalserver:appsDisplayAppDescription", + PortalPage.PORTAL_XML_NS); + descr.setText(apps.getDescription()); + + ps.setControlEvent(this, ApplicationsDisplay.CONFIG_APP, + apps.getID().toString()); + m_confLink.generateXML(ps, appElt); + + ApplicationCollection portlets = + apps.getApplication().getChildApplications(); + while (portlets.next()) { + Element port = + appElt.newChildElement("portalserver:appsDisplayAppPortlet", + PortalPage.PORTAL_XML_NS); + port.addAttribute("name", portlets.getTitle()); + + ps.setControlEvent(this, + ApplicationsDisplay.CONFIG_PORTLET, + portlets.getID().toString()); + m_confLink.generateXML(ps, port); + } + } + } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/BasicPane.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/BasicPane.java new file mode 100644 index 000000000..efa329b02 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/BasicPane.java @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.BoxPanel; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.Container; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.PropertySheet; +import com.arsdigita.bebop.PropertySheetModel; +import com.arsdigita.bebop.PropertySheetModelBuilder; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.FormInitListener; +import com.arsdigita.bebop.event.FormSubmissionListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.bebop.form.TextArea; +import com.arsdigita.bebop.form.TextField; +import com.arsdigita.bebop.parameters.NotEmptyValidationListener; +import com.arsdigita.portalserver.PortalSite; +import org.apache.log4j.Logger; + +public class BasicPane { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/admin/BasicPane.java#5 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static final Logger s_log = Logger.getLogger(BasicPane.class); + + private BasicPane() { + // No construction allowed + } + + public static Component create(final RequestLocal portalsite) { + final Container view = view(portalsite); + + final Component edit = edit(view, portalsite, new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState ps = e.getPageState(); + view.setVisible(ps, true); + } + }); + + final ActionLink editLink = new ActionLink( (String) GlobalizationUtil.globalize("cw.workspace.ui.admin.edit").localize()); + editLink.setClassAttr("actionLink"); + editLink.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState ps = e.getPageState(); + view.setVisible(ps, false); + edit.setVisible(ps, true); + } + }); + view.add(editLink); + + final ActionLink personalizeLink = new ActionLink( (String) GlobalizationUtil.globalize("cw.workspace.ui.admin.personalize").localize()) { + public boolean isVisible(PageState s) { + PortalSite psite = (PortalSite)portalsite.get(s); + if(!psite.isPersonalizable()) + return true; + else + return false; + } + }; + personalizeLink.setClassAttr("actionLink"); + personalizeLink.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState ps = e.getPageState(); + PortalSite psite = (PortalSite)portalsite.get(ps); + psite.setPersonalizable(true); + } + }); + view.add(personalizeLink); + + final ActionLink unpersonalizeLink = new ActionLink( (String) GlobalizationUtil.globalize("cw.workspace.ui.admin.unpersonalize").localize()) { + public boolean isVisible(PageState s) { + PortalSite psite = (PortalSite)portalsite.get(s); + if(psite.isPersonalizable()) + return true; + else + return false; + } + }; + unpersonalizeLink.setClassAttr("actionLink"); + unpersonalizeLink.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState ps = e.getPageState(); + PortalSite psite = (PortalSite)portalsite.get(ps); + psite.setPersonalizable(false); + } + }); + view.add(unpersonalizeLink); + + SimpleContainer retval = new SimpleContainer(); + + retval.add(view); + retval.add(edit); + + return retval; + } + + private static Component edit(final Component view, + final RequestLocal portalsite, + final ActionListener onDone) { + final Form editForm = new Form("editws") { + public void register(Page p) { + super.register(p); + p.setVisibleDefault(this, false); + } + }; + editForm.setMethod(Form.POST); + + editForm.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.title"))); + final TextField title = new TextField("title"); + title.setSize(40); + title.getParameterModel().addParameterListener + (new NotEmptyValidationListener()); + editForm.add(title); + + editForm.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.mission"))); + final TextArea mission = new TextArea("mission"); + mission.setRows(10); + mission.setCols(40); + editForm.add(mission); + + final Submit cancel = new Submit("cancel", "Cancel"); + editForm.add(cancel); + + editForm.add(new Submit("done", "Submit")); + + editForm.addInitListener(new FormInitListener() { + public void init(FormSectionEvent e) { + PageState ps = e.getPageState(); + PortalSite psite = (PortalSite) portalsite.get(ps); + title.setValue(ps, psite.getTitle()); + mission.setValue(ps, psite.getMission()); + } + }); + + editForm.addSubmissionListener(new FormSubmissionListener() { + public void submitted(FormSectionEvent e) + throws FormProcessException { + PageState ps = e.getPageState(); + + if (cancel.isSelected(ps)) { + view.setVisible(ps, true); + editForm.setVisible(ps, false); + throw new FormProcessException(""); + } + } + }); + + editForm.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent e) { + PageState ps = e.getPageState(); + PortalSite psite = (PortalSite) portalsite.get(ps); + psite.setTitle((String) title.getValue(ps)); + psite.setMission((String) mission.getValue(ps)); + psite.save(); + editForm.setVisible(ps, false); + onDone.actionPerformed(new ActionEvent(editForm, ps)); + } + }); + + return editForm; + } + + private static Container view(final RequestLocal portalsite) { + BoxPanel retval = new BoxPanel(BoxPanel.VERTICAL); + Label header = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.workspace_basic_properties")); + header.setFontWeight(Label.BOLD); + retval.add(header); + + retval.add(new PropertySheet(new PropertySheetModelBuilder() { + public void lock() { } + public boolean isLocked() { return true; } + public PropertySheetModel makeModel(PropertySheet sheet, + final PageState ps) { + return new RelatedPortalsPane.PortalModel((PortalSite)portalsite.get(ps)); + } + })); + + return retval; + } + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/ChildPortalCreateForm.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/ChildPortalCreateForm.java new file mode 100644 index 000000000..36120f3ba --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/ChildPortalCreateForm.java @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import java.math.BigDecimal; + +import com.arsdigita.bebop.BoxPanel; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Tree; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.ParameterSingleSelectionModel; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.FormInitListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.PrintEvent; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.bebop.event.ParameterEvent; +import com.arsdigita.bebop.event.ParameterListener; +import com.arsdigita.bebop.form.Option; +import com.arsdigita.bebop.form.RadioGroup; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.bebop.form.TextArea; +import com.arsdigita.bebop.form.TextField; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.bebop.parameters.NotEmptyValidationListener; +import com.arsdigita.bebop.parameters.ParameterData; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.bebop.tree.TreeModel; +import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.Party; +import com.arsdigita.kernel.permissions.PermissionDescriptor; +import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; +import com.arsdigita.portal.Portlet; +import com.arsdigita.portalserver.ApplicationDirectoryPortlet; +import com.arsdigita.portalserver.PortalSite; +import com.arsdigita.portalserver.PortalNavigatorPortlet; +import com.arsdigita.portalserver.PortalSummaryPortlet; +import com.arsdigita.portalserver.PortalTab; +import com.arsdigita.web.Application; +import com.arsdigita.bebop.form.TextArea; +import org.apache.log4j.Category; + +/** + *

    Form for initial Portal construction.

    + **/ +public class ChildPortalCreateForm { + public static String versionId = "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/admin/ChildPortalCreateForm.java#3 $ $Author: dennis $ $DateTime: 2004/08/17 23:19:25 $"; + + private static Category s_log = Category.getInstance(ChildPortalCreateForm.class); + + /** + * @param parentPortal an input request local holding the parent of the + * portal to be created + * @param portalsiteRL the newly created portal will be set in the + * portalsiteRL RequestLocal + * @param onFinish will be run when creation of the portal is complete; + * the source of the action event will be the returned Component + * @return a component for portalsite creation given a parent portal */ + public static Component create(final RequestLocal parentPortalSite, + final RequestLocal portalsiteRL, + final ActionListener onFinish) { + + final Form portalCreation = new Form("portalcreation"); + portalCreation.setMethod(Form.POST); + + NotEmptyValidationListener notWhiteSpace = + new NotEmptyValidationListener(); + + UniquePortalURLValidationListener uniqueURL = + new UniquePortalURLValidationListener(); + + portalCreation.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.parent_workspace"))); + portalCreation.add(new Label(new PrintListener() { + public void prepare(PrintEvent e) { + PageState ps = e.getPageState(); + Label target = (Label) e.getTarget(); + PortalSite psite = (PortalSite) parentPortalSite.get(ps); + if (psite == null) { + target.setLabel( (String) GlobalizationUtil.globalize("cw.workspace.ui.admin.none").localize()); + target.setFontWeight(Label.ITALIC); + } else { + target.setLabel(psite.getDisplayName()); + } + } + })); + + final TextField psName = new TextField(new StringParameter("psName")); + psName.getParameterModel().addParameterListener(notWhiteSpace); + portalCreation.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.title"))); + portalCreation.add(psName); + + final TextField psLocation = + new TextField(new StringParameter("psNode")); + psLocation.getParameterModel().addParameterListener(notWhiteSpace); + psLocation.getParameterModel().addParameterListener(uniqueURL); + psLocation.getParameterModel().addParameterListener( + new ParameterListener() { + public void validate(ParameterEvent e) { + ParameterData data = e.getParameterData(); + String value = (String) data.getValue(); + char[] chars = value.toCharArray(); + for (int i = 0; i < chars.length; i++) { + if (!(Character.isLetterOrDigit(chars[i]) + || chars[i] == '-' || chars[i] == '_')) { + data.addError( "Can only contain letters, numbers, dashes, and underscores"); + break; + } + } + }}); + portalCreation.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.url_fragment"))); + portalCreation.add(psLocation); + + final TextArea psMission = + new TextArea(new StringParameter("psMission")); + portalCreation.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.mission"))); + portalCreation.add(psMission); + + final RadioGroup psInherit = new RadioGroup("inherit_permissions"); + psInherit.addOption(new Option + ("inherit_false", + new Label(GlobalizationUtil.globalize + ("cw.workspace.ui.admin.inherit_permissions_no")))); + psInherit.addOption(new Option + ("inherit_true", + new Label(GlobalizationUtil.globalize + ("cw.workspace.ui.admin.inherit_permissions_yes")))); + portalCreation.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.inherit_permissions_prompt"))); + portalCreation.add(psInherit); + portalCreation.add(new Submit("done", "Create Portal")); + + portalCreation.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) + throws FormProcessException { + PageState ps = ev.getPageState(); + + PortalSite parent = (PortalSite) parentPortalSite.get(ps); + + String name = (String)psName.getValue(ps); + String location = (String)psLocation.getValue(ps); + String mission = (String)psMission.getValue(ps); + + boolean inheritPermissions = + !("inherit_false".equals((String)psInherit.getValue(ps))); + PortalSite psite = PortalSite.createPortalSite + (location, name, parent, inheritPermissions); + psite.setMission(mission); + psite.save(); + + // By default, add some workspace portlets. + PortalTab mainTab = PortalTab.createTab("Main",psite); + + Portlet portlet = Portlet.createPortlet + (ApplicationDirectoryPortlet.BASE_DATA_OBJECT_TYPE, psite); + mainTab.addPortlet(portlet, 1); + + portlet = Portlet.createPortlet + (PortalNavigatorPortlet.BASE_DATA_OBJECT_TYPE, psite); + mainTab.addPortlet(portlet, 1); + + portlet = Portlet.createPortlet + (PortalSummaryPortlet.BASE_DATA_OBJECT_TYPE, psite); + mainTab.addPortlet(portlet, 1); +/* + Application DocRepositoryApp = Application.createApplication + (Repository.BASE_DATA_OBJECT_TYPE, "documents", + "My Document Manager", ws); + DocRepositoryApp.save(); + + portlet = Portlet.createPortlet + (RecentUpdatedDocsPortlet.BASE_DATA_OBJECT_TYPE, + DocRepositoryApp); + mainTab.addPortlet(portlet, 2); +*/ + mainTab.setPortalSite(psite); + mainTab.save(); + psite.addPortalTab(mainTab); + psite.save(); + + portalsiteRL.set(ps, psite); + + Party party = Kernel.getContext().getParty(); + + if (party == null) { + throw new IllegalStateException("not logged in"); + } + psite.addMember(party); + psite.save(); + PermissionDescriptor perm = new PermissionDescriptor + (PrivilegeDescriptor.ADMIN, psite, party); + PermissionService.grantPermission(perm); + + onFinish.actionPerformed + (new ActionEvent(portalCreation, ps)); + } + }); + + return portalCreation; + } + + /** + * @param portalsiteRL the newly created portalsite will be set in the + * portalsiteRL RequestLocal + * @param onFinish will be run when creation of the portal is complete; + * the source of the action event will be the returned Component + * @return a component for portal creation + **/ + public static Component create(final RequestLocal portalsiteRL, + final ActionListener onFinish) { + + final SimpleContainer retval = new SimpleContainer(); + + final Tree psParent = new Tree(new PortalTreeModelBuilder()); + psParent.setSelectionModel( new ParameterSingleSelectionModel( + new BigDecimalParameter("psParent"))); + + final Form parentSelection = new Form("parentselection", + new BoxPanel(BoxPanel.VERTICAL)); + parentSelection.setMethod(Form.POST); + + RequestLocal parentPortal = new RequestLocal() { + protected Object initialValue(PageState ps) { + BigDecimal id = (BigDecimal) psParent.getSelectedKey(ps); + if (id == null) { return null; } + return PortalSite.retrievePortalSite(id); + } + }; + + final Component portalCreation = ChildPortalCreateForm.create( + parentPortal, portalsiteRL, new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState ps = e.getPageState(); + onFinish.actionPerformed(new ActionEvent(retval, ps)); + } + }); + + retval.add(parentSelection); + retval.add(portalCreation); + + parentSelection.addInitListener(new FormInitListener() { + public void init(FormSectionEvent e) { + PageState ps = e.getPageState(); + TreeModel tm = psParent.getTreeModel(ps); + portalCreation.setVisible(ps, false); + String key = (String) tm.getRoot(ps).getKey(); + if (psParent.isCollapsed(key, ps)) { + psParent.expand((String) tm.getRoot(ps).getKey(), ps); + } + } + }); + + parentSelection.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent e) { + PageState ps = e.getPageState(); + portalCreation.setVisible(ps, true); + parentSelection.setVisible(ps, false); + } + }); + + parentSelection.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.select_parent_workspace"))); + + psParent.setCellRenderer( + new PortalTreeModelBuilder.DefaultRenderer()); + + parentSelection.add(psParent); + + parentSelection.add(new Submit("Continue")); + + return retval; + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/DisplayPane.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/DisplayPane.java new file mode 100644 index 000000000..eb40aa36e --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/DisplayPane.java @@ -0,0 +1,701 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.web.ApplicationType; +import com.arsdigita.portalserver.PortalSite; +import com.arsdigita.portalserver.PortalTab; +import com.arsdigita.portalserver.PortalTabCollection; +import com.arsdigita.portal.Portlet; +import com.arsdigita.portal.PortletType; +import com.arsdigita.portal.PortletTypeCollection; + +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.BoxPanel; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.DynamicListWizard; +import com.arsdigita.bebop.Image; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.GridPanel; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.List; +import com.arsdigita.bebop.ModalContainer; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.form.Option; +import com.arsdigita.bebop.form.SingleSelect; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.bebop.form.TextField; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.ChangeEvent; +import com.arsdigita.bebop.event.ChangeListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.PrintEvent; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.bebop.parameters.NotNullValidationListener; +import com.arsdigita.bebop.parameters.NotEmptyValidationListener; +import com.arsdigita.bebop.list.ListCellRenderer; +import com.arsdigita.bebop.list.ListModel; +import com.arsdigita.bebop.list.ListModelBuilder; +import org.apache.log4j.Logger; +import java.util.TooManyListenersException; +import java.util.Vector; +import java.util.ListIterator; +import java.math.BigDecimal; + +/** + * Experimental + * + * @author Jim Parsons + * @author Eric Lorenzo + * @author Justin Ross + * @version $Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/admin/DisplayPane.java#9 $ + */ +public class DisplayPane extends DynamicListWizard { + public static final String versionId = "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/admin/DisplayPane.java#9 $ by $Author: dennis $, $DateTime: 2004/08/17 23:19:25 $"; + + private static final Logger s_cat = + Logger.getLogger(ApplicationsPane.class.getName()); + + final ModalContainer m_editContainer = new ModalContainer(); + + SimpleContainer m_mainDisplay; + ApplicationModifyComponent m_portletModify; + PortletAddForm m_portletAddForm; + RenameTabForm m_renameTabForm; + DeleteTabForm m_deleteTabForm; + List m_layouts; + RequestLocal selectedTabIDRL; + static final String m_layoutNames[] = {"W","NW","WN","NWN","NNN"}; + + BigDecimalParameter m_selectedPortletParam; + + static final String FOUR_SPACE_INDENT_STRING = "    "; + + static class TabListModel implements ListModel { + PortalTabCollection m_tabs; + PortalTab m_currTab; + public TabListModel(PortalSite psite) { + m_tabs = psite.getTabsForPortalSite(); + } + public boolean next() { + if (!m_tabs.next()) { + return false; + } + m_currTab = m_tabs.getPortalTab(); + return true; + } + public Object getElement() { + return m_currTab.getTitle(); + } + public String getKey() { + return m_currTab.getID().toString(); + } + } + + + + public DisplayPane(final RequestLocal portalsiteRL) + { + super("Current Tabs. Use the arrows to shift tab position.", + new ListModelBuilder() { + public ListModel makeModel(List l, PageState ps) { + PortalSite psite = (PortalSite)portalsiteRL.get(ps); + return new TabListModel(psite); + } + public void lock() {} + public boolean isLocked() { return true; } + }, + "Add a tab", + new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.there_currently_is_no_tab_selected_please_select_a_tab"))); + + final DynamicListWizard dlw = this; + + + // FORM FOR ADDING NEW TABS + Form addForm = new Form("addTab"); + + addForm.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.new_tab_name"))); + final TextField newTabName = new TextField("name"); + newTabName.getParameterModel().addParameterListener + (new NotEmptyValidationListener()); + newTabName.setSize(40); + addForm.add(newTabName); + addForm.add(new Label()); + addForm.add(new Submit("Add tab")); + + + addForm.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + PortalSite psite = (PortalSite)portalsiteRL.get(ps); + PortalTab newTab = + PortalTab.createTab((String)newTabName.getValue(ps),psite); + psite.addPortalTab(newTab); + newTab.save(); + psite.save(); + + List list = (List) dlw.getListingComponent(); + + list.getSelectionModel() + .setSelectedKey(ps, newTab.getID().toString()); + } + }); + + setAddPane(addForm); + + // CONSTRUCT EDIT COMPONENT + selectedTabIDRL = new RequestLocal() { + protected Object initialValue(PageState ps) { + String tabIDstr = (String)dlw.getSelectionModel() + .getSelectedKey(ps); + return new BigDecimal(tabIDstr); + } + }; + + m_selectedPortletParam = new BigDecimalParameter("selectedPortlet"); + + m_mainDisplay = new BoxPanel(BoxPanel.VERTICAL); + PortletLayoutComponent plc = + new PortletLayoutComponent(portalsiteRL, selectedTabIDRL) { + protected void handleConfigure(PageState ps, BigDecimal id) { + ps.setValue(m_selectedPortletParam, id); + m_editContainer.setVisibleComponent(ps, m_portletModify); + } + }; + LockableLinks locklinks = + new LockableLinks(portalsiteRL, selectedTabIDRL); + m_mainDisplay.add(locklinks); + m_mainDisplay.add(plc); + + BoxPanel links = new BoxPanel(BoxPanel.HORIZONTAL, true); + + ActionLink renameLink = new ActionLink( (String) GlobalizationUtil.globalize("cw.workspace.ui.admin.rename_tab").localize()); + renameLink.setClassAttr("actionLink"); + renameLink.addActionListener(new RenameLinkListener()); + links.add(renameLink); + + ActionLink deleteLink = new ActionLink( (String) GlobalizationUtil.globalize("cw.workspace.ui.admin.delete_tab").localize()) { + public boolean isVisible(PageState ps) { + PortalSite psite = (PortalSite)portalsiteRL.get(ps); + PortalTabCollection pstc = psite.getTabsForPortalSite(); + return (pstc.size() > 1); + } + }; + deleteLink.setClassAttr("actionLink"); + deleteLink.addActionListener(new DeleteLinkListener()); + links.add(deleteLink); + + m_mainDisplay.add(links); + + final BigDecimalParameter portletTypeParam = + new BigDecimalParameter("typeID"); + Form addPortlet = new Form("ap1", new GridPanel(1)) { + public void register(Page p) { + super.register(p); + p.addComponentStateParam(this, portletTypeParam); + } + }; + Image image = new Image("/assets/cw/general/add.gif"); + image.setBorder("0"); + + SimpleContainer imageLabelSC = new SimpleContainer(); + imageLabelSC.add(image); + imageLabelSC.add(new Label + ("To add a portlet to this page, first choose a type: ")); + + addPortlet.add(imageLabelSC); + + final SingleSelect portletTypeSelect = new SingleSelect("ptype"); + portletTypeSelect.addValidationListener( + new NotNullValidationListener()); + PortletTypeCollection ptc = PortletType.retrieveAllPortletTypes(); + //Alphabetize by title + ptc.addOrder("title"); + while (ptc.next()) { + ApplicationType providerAppType = ptc.getPortletType().getProviderApplicationType(); + if ( providerAppType != null ) { + portletTypeSelect.addOption(new Option(ptc.getID().toString(), ptc.getTitle() + + " (" + providerAppType.getTitle() + ") ")); + } else { + portletTypeSelect.addOption(new Option(ptc.getID().toString(), ptc.getTitle())); + } + } + + SimpleContainer selectorSC = new SimpleContainer(); + selectorSC.add(portletTypeSelect); + selectorSC.add(new Submit("Go")); + addPortlet.add(selectorSC); + + addPortlet.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + m_editContainer.setVisibleComponent(ps, m_portletAddForm); + ps.setValue(portletTypeParam, new BigDecimal( + (String) portletTypeSelect.getValue(ps))); + m_portletAddForm.activate(ps); + } + }); + m_mainDisplay.add(addPortlet); + + BoxPanel tabLayouts = new BoxPanel(BoxPanel.HORIZONTAL, true); + + ListModelBuilder lmb = new ListModelBuilder() + { + boolean m_isLocked; + + public ListModel makeModel(List l, PageState pageState) + { + return new LayoutListModel (pageState); + } + + public void lock() + { + m_isLocked = true; + } + + public boolean isLocked() + { + return m_isLocked; + } + }; + + m_layouts = new List(lmb); + + m_layouts.setClassAttr("tabLayouts"); + + m_layouts.setCellRenderer(new LayoutListCellRenderer()); + + m_layouts.addChangeListener(new ChangeListener () { + public void stateChanged(ChangeEvent e) + { + PageState ps = e.getPageState(); + String key = (String) ((List) dlw.getListingComponent()) + .getSelectedKey(ps); + BigDecimal bd = new BigDecimal(key); + PortalTab ptab = PortalTab.retrieveTab(bd); + String laykey = (String)m_layouts.getSelectedKey(ps); + Integer lk = new Integer(laykey); + ptab.setLayout(m_layoutNames[lk.intValue()]); + ptab.save(); + } + }); + + tabLayouts.add(m_layouts); + + m_mainDisplay.add(tabLayouts); + + + m_portletAddForm = + new PortletAddForm(portalsiteRL, selectedTabIDRL, new RequestLocal() { + protected Object initialValue(PageState ps) { + BigDecimal id = (BigDecimal) ps.getValue(portletTypeParam); + if (id == null) { + return null; + } + return PortletType.retrievePortletType(id); + } + }); + m_portletAddForm.addCompletionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + ps.reset(m_editContainer); + } + }); + + RequestLocal selectedPortletRL = new RequestLocal() { + public Object initialValue(PageState ps) { + BigDecimal portletID = + (BigDecimal)ps.getValue(m_selectedPortletParam); + if (portletID == null) { + return null; + } + return Portlet.retrievePortlet(portletID); + } + }; + ActionListener reset = new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + ps.reset(m_editContainer); + ps.setValue(m_selectedPortletParam, null); + } + }; + m_portletModify = new ApplicationModifyComponent + (selectedPortletRL, true, reset, reset); + + m_renameTabForm = new RenameTabForm(selectedTabIDRL); + m_deleteTabForm = new DeleteTabForm(selectedTabIDRL); + + m_editContainer.add(m_mainDisplay); + m_editContainer.add(m_portletModify); + m_editContainer.add(m_portletAddForm); + m_editContainer.add(m_renameTabForm); + m_editContainer.add(m_deleteTabForm); + setEditPane(m_editContainer); + + ((List) getListingComponent()).addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent ev) { + ev.getPageState().reset(m_editContainer); + } + }); + + // + //This cell renderer attempts to do the following: + //1) If tab name is selected, returns a label + //2) If not selected, returns a link + //3) If the tab name is selected, and: + // a) It is the first tab, a move_right arrow link is rendered + // b) It is the last tab, a move_left arrow link is rendered + // c) If there are more than two tabs, and it isn't first + // or last, both move_left and move_right arrows are shown. + //The arrows are implemented as control links with attr values... + //One other thing, if there is only one tab in the list, + //this code preselects it, unless the add tab link has been + //clicked. + + ((List) getListingComponent()).setCellRenderer(new ListCellRenderer() { + public Component getComponent(List list,PageState state, + Object value,String key, int index,boolean isSelected) { + + Label tabName; + int indent_ctr = 0; + boolean isFirst = false; + boolean isLast = false; + + SimpleContainer container = new SimpleContainer(); + + //get the collection of tabs, its size, and use this info + //to determine where in the collection this tab name resides... + BigDecimal bd = new BigDecimal(key); + PortalTab ptab = PortalTab.retrieveTab(bd); + PortalSite psite = ptab.getPortalSite(); + PortalTabCollection ptcoll = psite.getTabsForPortalSite(); + long size = ptcoll.size(); + + //If only one tab, select it ONLY if addtablink not selected + // and then get outa here... + if(size == 1) + { + if((dlw.getAddLink().isSelected(state)) == false) + { + list.setSelectedKey(state,key); + tabName = new Label(value.toString()); + container.add(tabName); + //Update tab request local + selectedTabIDRL.set(state,bd); + return container; + } + } + else //more than one tab... + { + indent_ctr = 0; + while(ptcoll.next()) + { + indent_ctr++; + if(bd.compareTo(ptcoll.getID()) == 0) //we found tab... + { + if(indent_ctr == 1) + isFirst = true; + if(indent_ctr == size) + isLast = true; + break; + } + } + } + ptcoll.close(); + + //Code below constructs proper indent for tab + StringBuffer buf = new StringBuffer(200); + for(int i = 0; i < (indent_ctr - 1); i++) + { + buf.append(FOUR_SPACE_INDENT_STRING); + } + + //Here we construct the control links for arrows + //This could be done below in the particular cases for + //a slight performance benefit, but putting them + //here, together, is easier to understand... + if(isSelected) //This tab name is currently selected... + { + tabName = new Label(value.toString()); + tabName.setFontWeight(Label.BOLD); + Label labelLeft = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.shift_left")); + Label labelRight = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.shift_right")); + + ControlLink linkLeft = new ControlLink(labelLeft) { + public void setControlEvent(PageState s) { + s.setControlEvent(dlw,"left","1"); + } + }; + ControlLink linkRight = new ControlLink(labelRight) { + public void setControlEvent(PageState s) { + s.setControlEvent(dlw,"right","1"); + } + }; + + linkLeft.setClassAttr("shiftleft"); + linkRight.setClassAttr("shiftright"); + if(isFirst) + { + container.add(tabName); + container.add(linkRight); + } + else if(isLast) + { + container.add(linkLeft); + container.add(tabName); + } + else //This tab is somewhere in the middle... + { + container.add(linkLeft); + container.add(tabName); + container.add(linkRight); + } + + } + else //this tab is NOT selected...return a link + { + String ttab = buf.toString() + value.toString(); + tabName = new Label(ttab,false); + ControlLink l = new ControlLink(tabName); + container.add(l); + } + return container; + } + }); + + + } //end of constructor + + public void register(Page p) { + super.register(p); + p.addComponentStateParam(this, m_selectedPortletParam); + } + + public void respond(PageState state) throws javax.servlet.ServletException{ + String tabIDstr = + (String)this.getSelectionModel() + .getSelectedKey(state); + + BigDecimal tabID = new BigDecimal(tabIDstr); + + String name = state.getControlEventName(); + if(name.compareTo("left") == 0) { + PortalTab ptab = PortalTab.retrieveTab(tabID); + PortalSite psite = ptab.getPortalSite(); + psite.swapTabWithPrevious(ptab); + } else if(name.compareTo("right") == 0) { + PortalTab ptab = PortalTab.retrieveTab(tabID); + PortalSite psite = ptab.getPortalSite(); + psite.swapTabWithNext(ptab); + } + } + + + public class RenameTabForm extends Form implements FormProcessListener { + private TextField currenttabName; + private Label instruction; + private Submit button,cancelbutton; + private RequestLocal m_tabIDRL; + + public RenameTabForm(RequestLocal SelectedTabIDRL) { + super("renametabform"); + m_tabIDRL = SelectedTabIDRL; + + instruction = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.enter_new_name_for_this_tab_in_text_field")); + currenttabName = new TextField("CurrentTabName"); + currenttabName.setDefaultValue(""); + currenttabName.setSize(40); + currenttabName.addValidationListener + (new NotNullValidationListener("Every Tab must have a name!")); + try { + currenttabName.addPrintListener(new PrintListener() { + public void prepare(PrintEvent e) { + PageState s = e.getPageState(); + BigDecimal tabID = (BigDecimal)m_tabIDRL.get(s); + PortalTab ptab = PortalTab.retrieveTab(tabID); + TextField tf = (TextField)e.getTarget(); + tf.setValue(s,ptab.getTitle()); + } + }); + } catch(java.util.TooManyListenersException e) { } + button = new Submit("Rename tab"); + button.setButtonLabel("Rename tab"); + cancelbutton = new Submit("Cancel"); + cancelbutton.setButtonLabel("Cancel"); + this.add(instruction); + this.add(currenttabName); + this.add(button); + this.add(cancelbutton); + this.addProcessListener(this); + } + + public void process(FormSectionEvent e) { + PageState s = e.getPageState(); + + if(button.isSelected(s)) { + BigDecimal tabID = (BigDecimal)m_tabIDRL.get(s); + PortalTab ptab = PortalTab.retrieveTab(tabID); + ptab.setTitle(currenttabName.getValue(s).toString()); + ptab.save(); + } + + s.reset(m_editContainer); + } + } //end rename form + + public class DeleteTabForm extends Form implements FormProcessListener { + private TextField currenttabName; + private Label instruction; + private Submit button; + private Submit cancelbutton; + private RequestLocal m_tabIDRL; + + + public DeleteTabForm(RequestLocal SelectedTabIDRL) { + super("deletetabform"); + m_tabIDRL = SelectedTabIDRL; + + instruction = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.are_you_sure_you_want_to_delete_this_tab")); + instruction.addPrintListener(new PrintListener() { + public void prepare(PrintEvent e) { + PageState s = e.getPageState(); + String prefixstr = "Are you sure you want to delete the "; + BigDecimal tabID = (BigDecimal)m_tabIDRL.get(s); + PortalTab ptab = PortalTab.retrieveTab(tabID); + Label t = (Label)e.getTarget(); + t.setLabel(prefixstr + ptab.getTitle() + " tab?"); + } + }); + + button = new Submit("Delete this tab"); + button.setButtonLabel("Delete this tab"); + cancelbutton = new Submit("Cancel"); + cancelbutton.setButtonLabel("Cancel"); + this.add(instruction); + this.add(button); + this.add(cancelbutton); + this.addProcessListener(this); + } + + public void process(FormSectionEvent e) { + PageState s = e.getPageState(); + + if(button.isSelected(s)) { + BigDecimal tabID = (BigDecimal)m_tabIDRL.get(s); + PortalTab ptab = PortalTab.retrieveTab(tabID); + ptab.delete(); + getSelectionModel().clearSelection(s); + reset(s); + } + s.reset(m_editContainer); + } + } //end delete form + + private class RenameLinkListener implements ActionListener { + public void actionPerformed(ActionEvent event) { + PageState ps = event.getPageState(); + m_editContainer.setVisibleComponent(ps, m_renameTabForm); + } + } + + private class DeleteLinkListener implements ActionListener { + public void actionPerformed(ActionEvent event) { + PageState ps = event.getPageState(); + m_editContainer.setVisibleComponent(ps, m_deleteTabForm); + } + } + + private class LayoutListModel implements ListModel + { + Vector vec; + ListIterator vl; + + LayoutListModel (PageState pageState) + { + vec = new Vector(); + vec.add("W"); + vec.add("NW"); + vec.add("WN"); + vec.add("NWN"); + vec.add("NNN"); + + vl = vec.listIterator(); + } + + public boolean next() + { + return vl.hasNext(); + } + + public Object getElement() + { + return vl.next(); + } + + public String getKey() + { + int dex = vl.previousIndex(); + dex = dex + 1; + //Integer it = new Integer(vl.previousIndex()); + Integer it = new Integer(dex); + return it.toString(); + } + } + + class LayoutListCellRenderer implements ListCellRenderer + { + public Component getComponent + (List list, PageState pageState, Object value, String key, + int index, boolean isSelected) + { + String val = (String)value; + //check if selected...if not selected + //find out what index we are... + //then set an attribute on the link so that it is replaced + //with an image link in the stylesheet. + //if selected, return a label with a selected attr and value... + if(isSelected) + { + Label label = new Label(val); + label.setClassAttr(val); + return label; + } + else + { + ControlLink link = new ControlLink(val); + link.setClassAttr(val); + link.setStyleAttr("HooHaH"); + return link; + } + + } + } + + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/Initializer.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/Initializer.java new file mode 100644 index 000000000..d901bc269 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/Initializer.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + +import com.arsdigita.domain.DomainObject; +import com.arsdigita.initializer.Configuration; +import com.arsdigita.initializer.InitializationException; +import com.arsdigita.web.Application; +import com.arsdigita.web.ApplicationType; +import com.arsdigita.web.ApplicationSetup; +import com.arsdigita.kernel.ACSObjectInstantiator; +// import com.arsdigita.kernel.BaseInitializer; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.TransactionContext; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.portalserver.*; + +import org.apache.log4j.Logger; + +//public class Initializer extends BaseInitializer { +public class Initializer { + public static final String versionId = "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/admin/Initializer.java#9 $ by $Author: dennis $, $DateTime: 2004/08/17 23:19:25 $"; + + private static Logger s_log = Logger.getLogger(Initializer.class); + + private Configuration m_conf = new Configuration(); + + public Initializer() throws InitializationException { + /* Empty */ + } + + public Configuration getConfiguration() { + return m_conf; + } + + public final void doStartup() { + TransactionContext txn = SessionManager.getSession() + .getTransactionContext(); + + txn.beginTxn(); + + ApplicationType type = setupPortalCreator(); + setupPortalCreate(type); + + ApplicationType atype = setupPortalSitemapper(); + setupPortalSitemap(atype); + + txn.commitTxn(); + } + + private ApplicationType setupPortalCreator() { + ApplicationSetup setup = new ApplicationSetup(s_log); + setup.setApplicationObjectType(PortalCreator.BASE_DATA_OBJECT_TYPE); + setup.setTitle("Portal Creator"); + setup.setDescription("Creates portals."); + setup.setWorkspaceApplication(false); + setup.setKey("portal-create"); +// setup.setStylesheet("/packages/portalserver/xsl/portalserver.xsl"); + setup.setDispatcherClass( + "com.arsdigita.portalserver.ui.admin.PortalCreateDispatcher"); + setup.setInstantiator(new ACSObjectInstantiator() { + protected DomainObject doNewInstance(DataObject dataObject) { + return new PortalCreator(dataObject); + } + }); + + return setup.run(); + } + + private void setupPortalCreate(ApplicationType type) { + if (!Application.isInstalled(PortalCreator.BASE_DATA_OBJECT_TYPE, + "/portal-admin/portal-create/")) { + Application admin = + Application.retrieveApplicationForPath("/portal-admin/"); + + if (admin == null) { + s_log.warn("There is no application at /portal-admin/ so I " + + "can't install the portal create application."); + return; + } + + s_log.info("There is no Portal Creator application instance " + + "on /user-profile/. Installing now."); + + Application app = Application.createApplication + (type, "portal-create", "Create Top-Level Portals", admin); + app.setDescription("Create top-level portals."); + + app.save(); + + s_log.info("Done installing Portal Creator on " + + "/portal-admin/portal-create/."); + } + } + + private ApplicationType setupPortalSitemapper() { + ApplicationSetup setup = new ApplicationSetup(s_log); + setup.setApplicationObjectType(PortalSiteMap.BASE_DATA_OBJECT_TYPE); + setup.setTitle("Portal Site Map"); + setup.setDescription("Displays and manages Portals"); + setup.setWorkspaceApplication(false); + setup.setKey("portal-sitemap"); +// setup.setStylesheet("/packages/portalserver/xsl/portal-sitemap.xsl"); + setup.setDispatcherClass( + "com.arsdigita.portalserver.ui.admin.PortalSiteMapDispatcher"); + setup.setInstantiator(new ACSObjectInstantiator() { + protected DomainObject doNewInstance(DataObject dataObject) { + return new PortalSiteMap(dataObject); + } + }); + + return setup.run(); + } + + private void setupPortalSitemap(ApplicationType type) { + if (!Application.isInstalled(PortalSiteMap.BASE_DATA_OBJECT_TYPE, + "/portal-admin/portal-sitemap/")) { + Application admin = + Application.retrieveApplicationForPath("/portal-admin/"); + + if (admin == null) { + s_log.warn("There is no application at /portal-admin/ so I " + + "can't install the portal sitemap application."); + return; + } + + s_log.warn("There is no Portal Site Map application instance " + + "on /portal-admin/. Installing now."); + + Application app = Application.createApplication + (type, "portal-sitemap", "Portal Site Map", admin); + app.setDescription("Portal Site Map"); + + app.save(); + + s_log.warn("Done installing Portal Site Map on " + + "/portal-admin/portal-sitemap/."); + } + } + + public final void doShutdown() {} +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/LockableLinks.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/LockableLinks.java new file mode 100644 index 000000000..a50485550 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/LockableLinks.java @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import java.io.IOException; + +import java.math.BigDecimal; + + +import com.arsdigita.portalserver.PortalTab; +import com.arsdigita.portalserver.PortalSite; + +import com.arsdigita.portal.Portal; +import com.arsdigita.portal.Portlet; +import com.arsdigita.portal.PortletCollection; + +import com.arsdigita.xml.Element; + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.SimpleComponent; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.util.BebopConstants; +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.event.PrintEvent; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; + + + +/** + *

    This component provides UI for locking and unlocking + * the layout cells of a single portal.

    + **/ +public class LockableLinks + extends SimpleContainer + implements BebopConstants { + + private static final String NARROW_UNLOCKED = "N"; + private static final String NARROW_LOCKED = "n"; + private static final String WIDE_UNLOCKED = "W"; + private static final String WIDE_LOCKED = "w"; + + + private final RequestLocal m_portalsiteRL; + private final RequestLocal m_portalIDRL; + + ActionLink columnOneLink; + ActionLink columnTwoLink; + ActionLink columnThreeLink; + + + public LockableLinks(RequestLocal portalsiteRL, RequestLocal portalIDRL) { + + m_portalsiteRL = portalsiteRL; + m_portalIDRL = portalIDRL; + + + Label columnOneLinkLabel = new Label("Lock/Unlock"); + columnOneLinkLabel.addPrintListener(new PrintListener() { + public void prepare(PrintEvent e) { + PageState s = e.getPageState(); + Label t = (Label)e.getTarget(); + BigDecimal prtlID = (BigDecimal)m_portalIDRL.get(s); + PortalTab ptab = PortalTab.retrieveTab(prtlID); + if(ptab != null) { + String layout = ptab.getLayout(); + if(layout != null) { + String frag = layout.substring(0,1); + if(frag.compareTo(NARROW_LOCKED) == 0) { + t.setLabel(GlobalizationUtil. + globalize("portalserver.ui.admin.unlock_column")); + } else if (frag.compareTo(NARROW_UNLOCKED) == 0) { + t.setLabel(GlobalizationUtil. + globalize("portalserver.ui.admin.lock_column")); + } else if(frag.compareTo(WIDE_LOCKED) == 0) { + t.setLabel(GlobalizationUtil. + globalize("portalserver.ui.admin.unlock_column")); + } else if(frag.compareTo(WIDE_UNLOCKED) == 0) { + t.setLabel(GlobalizationUtil. + globalize("portalserver.ui.admin.lock_column")); + } + } + } + else { + return; + } + } + }); + columnOneLink = new ActionLink(columnOneLinkLabel); + columnOneLink.setIdAttr("columnonelocklink"); + columnOneLink.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState s = e.getPageState(); + BigDecimal prtlID = (BigDecimal)m_portalIDRL.get(s); + PortalTab ptab = PortalTab.retrieveTab(prtlID); + if(ptab != null) { + String layout = ptab.getLayout(); + if(layout != null) { + char c = layout.charAt(0); + String frag; + if(layout.length() > 1) + frag = layout.substring(1); + else + frag = ""; + if(c == 'n') { + ptab.setLayout("N" + frag); + } else if(c == 'N') { + ptab.setLayout("n" + frag); + } else if(c == 'w') { + ptab.setLayout("W" + frag); + } else if(c == 'W') { + ptab.setLayout("w" + frag); + } + ptab.save(); + } + } + } + }); + + Label columnTwoLinkLabel = new Label("Lock/Unlock"); + columnTwoLinkLabel.addPrintListener(new PrintListener() { + public void prepare(PrintEvent e) { + PageState s = e.getPageState(); + Label t = (Label)e.getTarget(); + BigDecimal prtlID = (BigDecimal)m_portalIDRL.get(s); + PortalTab ptab = PortalTab.retrieveTab(prtlID); + if(ptab != null) { + String layout = ptab.getLayout(); + if(layout != null) { + if(layout.length() < 2) + return; + String frag = layout.substring(1,2); + if(frag.compareTo(NARROW_LOCKED) == 0) { + t.setLabel(GlobalizationUtil. + globalize("portalserver.ui.admin.unlock_column")); + } else if (frag.compareTo(NARROW_UNLOCKED) == 0) { + t.setLabel(GlobalizationUtil. + globalize("portalserver.ui.admin.lock_column")); + } else if(frag.compareTo(WIDE_LOCKED) == 0) { + t.setLabel(GlobalizationUtil. + globalize("portalserver.ui.admin.unlock_column")); + } else if(frag.compareTo(WIDE_UNLOCKED) == 0) { + t.setLabel(GlobalizationUtil. + globalize("portalserver.ui.admin.lock_column")); + } + } + } + else { + return; + } + } + }); + columnTwoLink = new ActionLink(columnTwoLinkLabel) { + public boolean isVisible(PageState s) { + BigDecimal prtlID = (BigDecimal)m_portalIDRL.get(s); + PortalTab ptab = PortalTab.retrieveTab(prtlID); + if(ptab != null) { + String layout = ptab.getLayout(); + if(layout != null) { + if(layout.length() < 2) + return false; + else + return true; + } + } + return false; + } + }; + columnTwoLink.setIdAttr("columntwolocklink"); + columnTwoLink.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState s = e.getPageState(); + BigDecimal prtlID = (BigDecimal)m_portalIDRL.get(s); + PortalTab ptab = PortalTab.retrieveTab(prtlID); + if(ptab != null) { + String layout = ptab.getLayout(); + if(layout != null && layout.length() > 1) { + char c = layout.charAt(1); + String fragbegin = layout.substring(0,1); + String fragend; + if(layout.length() == 3) + fragend = layout.substring(2,3); + else + fragend = ""; + if(c == 'n') { + ptab.setLayout(fragbegin + "N" + fragend); + } else if(c == 'N') { + ptab.setLayout(fragbegin + "n" + fragend); + } else if(c == 'w') { + ptab.setLayout(fragbegin + "W" + fragend); + } else if(c == 'W') { + ptab.setLayout(fragbegin + "w" + fragend); + } + ptab.save(); + } + } + } + }); + + Label columnThreeLinkLabel = new Label("Lock/Unlock"); + columnThreeLinkLabel.addPrintListener(new PrintListener() { + public void prepare(PrintEvent e) { + PageState s = e.getPageState(); + Label t = (Label)e.getTarget(); + BigDecimal prtlID = (BigDecimal)m_portalIDRL.get(s); + PortalTab ptab = PortalTab.retrieveTab(prtlID); + if(ptab != null) { + String layout = ptab.getLayout(); + if(layout != null) { + if(layout.length() < 3) + return; + String frag = layout.substring(2,3); + if(frag.compareTo(NARROW_LOCKED) == 0) { + t.setLabel(GlobalizationUtil. + globalize("portalserver.ui.admin.unlock_column")); + } else if (frag.compareTo(NARROW_UNLOCKED) == 0) { + t.setLabel(GlobalizationUtil. + globalize("portalserver.ui.admin.lock_column")); + } else if(frag.compareTo(WIDE_LOCKED) == 0) { + t.setLabel(GlobalizationUtil. + globalize("portalserver.ui.admin.unlock_column")); + } else if(frag.compareTo(WIDE_UNLOCKED) == 0) { + t.setLabel(GlobalizationUtil. + globalize("portalserver.ui.admin.lock_column")); + } + } + } + else { + return; + } + } + }); + columnThreeLink = new ActionLink(columnThreeLinkLabel) { + public boolean isVisible(PageState s) { + BigDecimal prtlID = (BigDecimal)m_portalIDRL.get(s); + PortalTab ptab = PortalTab.retrieveTab(prtlID); + if(ptab != null) { + String layout = ptab.getLayout(); + if(layout != null) { + if(layout.length() < 3) + return false; + else + return true; + } + } + return false; + } + }; + columnThreeLink.setIdAttr("columnthreelocklink"); + columnThreeLink.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState s = e.getPageState(); + BigDecimal prtlID = (BigDecimal)m_portalIDRL.get(s); + PortalTab ptab = PortalTab.retrieveTab(prtlID); + if(ptab != null) { + String layout = ptab.getLayout(); + if(layout != null && layout.length() > 2) { + char c = layout.charAt(2); + String fragbegin = layout.substring(0,2); + if(c == 'n') { + ptab.setLayout(fragbegin + "N"); + } else if(c == 'N') { + ptab.setLayout(fragbegin + "n"); + } else if(c == 'w') { + ptab.setLayout(fragbegin + "W"); + } else if(c == 'W') { + ptab.setLayout(fragbegin + "w"); + } + ptab.save(); + } + } + } + }); + + add(columnOneLink); + add(columnTwoLink); + add(columnThreeLink); + } + + public boolean isVisible(PageState s) { + PortalSite ps = (PortalSite)m_portalsiteRL.get(s); + if(!ps.isPersonalizable()) + return false; + else + return true; + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PeoplePane.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PeoplePane.java new file mode 100644 index 000000000..4d11dcc0a --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PeoplePane.java @@ -0,0 +1,398 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.BoxPanel; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.DynamicListWizard; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.List; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.PrintEvent; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.bebop.list.ListModel; +import com.arsdigita.bebop.list.ListModelBuilder; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.kernel.PartyCollection; +import com.arsdigita.kernel.ui.ACSObjectSelectionModel; +import com.arsdigita.portalserver.PortalSite; +import org.apache.log4j.Category; + +import com.arsdigita.portalserver.permissions.PartyPermissionEdit; + +import com.arsdigita.kernel.ui.ACSObjectSelectionModel; +import com.arsdigita.toolbox.ui.ACSObjectCollectionListModel; + +import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.KernelExcursion; +import com.arsdigita.kernel.permissions.*; +import com.arsdigita.portalserver.*; +import com.arsdigita.portalserver.ui.*; +import com.arsdigita.bebop.*; +import com.arsdigita.bebop.list.*; +import com.arsdigita.bebop.form.*; +import com.arsdigita.bebop.event.*; +import com.arsdigita.bebop.parameters.*; +import com.arsdigita.bebop.list.ListModelBuilder; +import com.arsdigita.bebop.list.ListModel; + +public class PeoplePane { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/admin/PeoplePane.java#8 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static final Category s_log = Category.getInstance + (PeoplePane.class.getName()); + + private PeoplePane() { + // No construction allowed. + } + + public static Component create(Page page, final RequestLocal portalsite) { + final SimpleContainer container = new SimpleContainer(); + + final DynamicListWizard roles = + (DynamicListWizard) buildRoles(portalsite); + + final StringParameter action = new StringParameter("action"); + page.addGlobalStateParam(action); + + final DynamicListWizard browse = (DynamicListWizard) + ParticipantBrowsePane.createForAdmin + (portalsite, action, new ActionListener() { + public void actionPerformed(ActionEvent ev) { + // No thing + } + }); + + roles.getAddLink().addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + browse.reset(e.getPageState()); + } + }); + + roles.getSelectionModel().addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + PageState ps = e.getPageState(); + if (roles.getSelectionModel().isSelected(ps)) { + browse.reset(e.getPageState()); + } + } + }); + + browse.getAddLink().addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + roles.reset(e.getPageState()); + } + }); + + browse.getSelectionModel().addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + PageState ps = e.getPageState(); + if (browse.getSelectionModel().isSelected(ps)) { + roles.reset(e.getPageState()); + } + } + }); + + container.add(browse); + + container.add(roles); + + return container; + } + + private static Component buildRoles(final RequestLocal portalsiteRL) { + final ACSObjectSelectionModel selectionModel = + new ACSObjectSelectionModel("selectedRole"); + + List rList = new List(new ListModelBuilder() { + public ListModel makeModel(List l, PageState ps) { + PortalSite psite = (PortalSite) portalsiteRL.get(ps); + return new ACSObjectCollectionListModel(psite.getRoles()) { + public Object getElement() { + RoleCollection rc = (RoleCollection) getCollection(); + + if (rc.isSystem()) { + return rc.getRoleName() + "*"; + } else { + return rc.getRoleName(); + } + } + }; + } + + public void lock() { + // Do nothing. + } + + public boolean isLocked() { + return true; + } + }); + rList.setSelectionModel(selectionModel); + Label emptyView = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.no_roles_defined")); + emptyView.setFontWeight(Label.ITALIC); + rList.setEmptyView(emptyView); + + final DynamicListWizard dlw = new DynamicListWizard + ("Portal Roles", rList, selectionModel, "Add a role", + new Label("")); + + final RequestLocal role = new RequestLocal() { + public Object initialValue(PageState ps) { + return (Role) selectionModel.getSelectedObject(ps); + } + }; + + dlw.setAddPane(buildRolesAdd(role, portalsiteRL, new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + selectionModel.setSelectedObject(ps, (Role) role.get(ps)); + } + })); + + dlw.setEditPane(buildRolesEdit(role, portalsiteRL, new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + selectionModel.setSelectedObject(ps, null); + } + })); + + return dlw; + } + + private static Component buildRolesAdd(final RequestLocal roleRL, + final RequestLocal portalsiteRL, + final ActionListener onAdd) { + final Form result = new Form("roleAdd"); + + result.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.role_name"))); + + final TextField roleNameField = new TextField("roleName"); + roleNameField + .getParameterModel() + .addParameterListener(new NotEmptyValidationListener()); + + result.add(roleNameField); + + result.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.assignee_title"))); + + final TextField assigneeTitleField = new TextField("assigneeTitle"); + assigneeTitleField + .getParameterModel() + .addParameterListener(new NotEmptyValidationListener()); + + result.add(assigneeTitleField); + + result.add(new Label()); + result.add(new Submit("Add Role")); + + result.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + String roleName = (String)roleNameField.getValue(ps); + String assigneeTitle = (String)assigneeTitleField.getValue(ps); + // XXX: creating roles with no descriptions + PortalSite psite = (PortalSite) portalsiteRL.get(ps); + Role newRole = + Role.createRole((PortalSite) portalsiteRL.get(ps), + roleName, assigneeTitle, ""); + newRole.save(); + PermissionService.grantPermission( + new PermissionDescriptor(PrivilegeDescriptor.READ,psite, newRole)); + roleRL.set(ps, newRole); + onAdd.actionPerformed(new ActionEvent(result, ps)); + } + }); + + return result; + } + + private static Component buildRolesEdit(final RequestLocal roleRL, + final RequestLocal portalsiteRL, + final ActionListener onDelete) { + final BoxPanel result = new BoxPanel(); + result.setWidth("100%"); + + GridPanel formPanel = new GridPanel(2); + // formPanel.setWidth("100%"); + final Form properties = new Form("roleEdit", formPanel); + + properties.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.role_name"))); + + final TextField roleNameEntry = new TextField("roleName") { + public boolean isVisible(PageState ps) { + Role r = (Role)roleRL.get(ps); + return ((r != null) && !r.isSystem()); + } + }; + roleNameEntry.addValidationListener(new NotEmptyValidationListener()); + + final Label roleNameDisplay = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.null_role")) { + public boolean isVisible(PageState ps) { + Role r = (Role)roleRL.get(ps); + return !roleNameEntry.isVisible(ps); + } + }; + roleNameDisplay.addPrintListener(new PrintListener() { + public void prepare(PrintEvent ev) { + Role r = (Role)roleRL.get(ev.getPageState()); + if (r == null) { + return; + } + Label tgt = (Label)ev.getTarget(); + tgt.setLabel(r.getRoleName()); + } + }); + + + final SimpleContainer roleNameComposite = new SimpleContainer(); + roleNameComposite.add(roleNameEntry); + roleNameComposite.add(roleNameDisplay); + properties.add(roleNameComposite); + + properties.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.assignee_title"))); + + final TextField titleEntry = new TextField("assigneeTitle") { + public boolean isVisible(PageState ps) { + return roleNameEntry.isVisible(ps); + } + }; + titleEntry.addValidationListener( + new NotEmptyValidationListener()); + + final Label titleDisplay = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.null_assignee_title")) { + public boolean isVisible(PageState ps) { + return roleNameDisplay.isVisible(ps); + } + }; + titleDisplay.addPrintListener(new PrintListener() { + public void prepare(PrintEvent ev) { + Role r = (Role)roleRL.get(ev.getPageState()); + if (r == null) { + return; + } + Label tgt = (Label) ev.getTarget(); + tgt.setLabel(r.getAssigneeTitle()); + } + }); + + final SimpleContainer titleComposite = new SimpleContainer(); + titleComposite.add(titleEntry); + titleComposite.add(titleDisplay); + properties.add(titleComposite); + + + properties.add(new Label()); + properties.add(new Submit("Update Role") { + public boolean isVisible(PageState ps) { + return roleNameEntry.isVisible(ps); + } + }); + + properties.addInitListener(new FormInitListener() { + public void init(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + Role role = (Role) roleRL.get(ps); + roleNameEntry.setValue(ps, role.getRoleName()); + } + }); + + properties.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) + throws FormProcessException { + PageState ps = ev.getPageState(); + Role role = (Role) roleRL.get(ps); + if (!role.isSystem()) { + String newRoleName = (String) roleNameEntry.getValue(ps); + String newTitle = (String) titleEntry.getValue(ps); + role.setRoleName(newRoleName); + role.setAssigneeTitle(newTitle); + role.save(); + } + } + }); + result.add(properties); + + final ActionLink deleteRole = new ActionLink( (String) GlobalizationUtil.globalize("cw.workspace.ui.admin.delete_role").localize()) { + public boolean isVisible(PageState ps) { + Role r = (Role) roleRL.get(ps); + return !r.isSystem(); + } + }; + deleteRole.setConfirmation( + "Really delete portal role?"); + deleteRole.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState ps = e.getPageState(); + final Role r = (Role) roleRL.get(ps); + r.getPortalSite().assertPrivilege(PrivilegeDescriptor.ADMIN); + KernelExcursion ex = new KernelExcursion() { + protected void excurse() { + setEffectiveParty(Kernel.getSystemParty()); + r.delete(); + } + }; + ex.run(); + onDelete.actionPerformed(new ActionEvent(result, ps)); + } + }); + result.add(deleteRole); + + final PartyPermissionEdit permWidget = + new PartyPermissionEdit("Privileges", portalsiteRL, roleRL); + result.add(permWidget); + + return result; + } + + private static class ParticipantsModel implements ListModel { + private PartyCollection m_parties; + + public ParticipantsModel(PortalSite psite) { + m_parties = psite.getParticipants(); + } + + public boolean next() { + return m_parties.next(); + } + + public String getKey() { + return m_parties.getID().toString(); + } + + public Object getElement() { + return m_parties.getDisplayName(); + } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalAdminPage.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalAdminPage.java new file mode 100644 index 000000000..6a853696c --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalAdminPage.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + + +import com.arsdigita.bebop.Container; +import com.arsdigita.bebop.DimensionalNavbar; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.TabbedPane; +import com.arsdigita.portalserver.ApplicationAuthenticationListener; +import com.arsdigita.portalserver.PortalSite; +import com.arsdigita.portalserver.PortalPage; + +import com.arsdigita.xml.Document; +import com.arsdigita.xml.Element; + +import org.apache.log4j.Category; + +public class PortalAdminPage extends PortalPage { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/admin/PortalAdminPage.java#8 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static Category s_log = Category.getInstance + (PortalAdminPage.class.getName()); + + RequestLocal m_portalsiteRL; + + public PortalAdminPage() { + super(); + + this.setClassAttr("portalserveradmin"); + + getHeader().setIdAttr("admin"); + + m_portalsiteRL = new RequestLocal() { + protected Object initialValue(PageState ps) { + return PortalSite.getCurrentPortalSite(ps.getRequest()); + } + }; + + addRequestListener(new ApplicationAuthenticationListener("admin")); + + lock(); + } + + protected void buildContextBar() { + DimensionalNavbar navbar = new DimensionalNavbar(); + + navbar.setClassAttr("portalNavbar"); + + navbar.add(new Link(new PersonalPortalLinkPrinter())); + navbar.add(new Link(new CurrentPortalLinkPrinter())); + navbar.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.configure_workspace"))); + + getHeader().add(navbar); + } + + protected void buildHeader(Container header) { + Link returnLink = new Link( new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.return_to_workspace")), "../"); + + returnLink.setClassAttr("portalControl"); + + header.add(returnLink); + } + + protected void buildBody(Container body) { + TabbedPane pane = new TabbedPane(); + + pane.setClassAttr("portalserver_admin"); + + pane.addTab("Layout", new DisplayPane(m_portalsiteRL)); + pane.addTab("Themes", new ThemesPane(m_portalsiteRL)); + pane.addTab("Applications", ApplicationsPane.create(m_portalsiteRL)); + pane.addTab("People", PeoplePane.create(this, m_portalsiteRL)); + pane.addTab("Related Portals", + RelatedPortalsPane.create(m_portalsiteRL)); + pane.addTab("Basic Properties", BasicPane.create(m_portalsiteRL)); + + body.add(pane); + body.setClassAttr("portalserver_admin"); + } + + public void addStyleBlock(PageState state, Document parent) { + PortalSite psite = PortalSite.getCurrentPortalSite(state.getRequest()); + + StringBuffer buffer = new StringBuffer(); + + buffer.append(""); + + Element rootElement = parent.getRootElement(); + + Element styleBlock = rootElement.newChildElement( + "portalserver:styleblock", + "http://www.redhat.com/portalserver/1.0"); + + styleBlock.setCDATASection(buffer.toString()); + + } + + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalArchivePage.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalArchivePage.java new file mode 100644 index 000000000..6c6348ffe --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalArchivePage.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.DimensionalNavbar; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.portalserver.ApplicationPage; +import com.arsdigita.portalserver.PortalSite; + +class PortalArchivePage extends ApplicationPage { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/admin/PortalArchivePage.java#4 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + public PortalArchivePage() { + + // TODO: parent portal selection after basic properties entered + //final Component panel = new PortalArchivePanel(this); + final Component panel = new PortalSiteMapPanel(this); + + add(panel); + + } + + protected void buildContextBar() { + DimensionalNavbar navbar = new DimensionalNavbar(); + navbar.setClassAttr("portalNavbar"); + + navbar.add(new Link(new PersonalPortalLinkPrinter())); + navbar.add(new Link(new ParentApplicationLinkPrinter())); + navbar.add(new Label(new CurrentApplicationLabelPrinter())); + + getHeader().add(navbar); + } + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalArchivePanel.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalArchivePanel.java new file mode 100644 index 000000000..755fb5862 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalArchivePanel.java @@ -0,0 +1,396 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; +import java.util.Date; +import java.text.SimpleDateFormat; +import com.arsdigita.portalserver.PortalSite; +import com.arsdigita.portalserver.PortalSiteCollection; +import com.arsdigita.portalserver.PortalPage; +import com.arsdigita.portalserver.personal.PersonalPortal; +import com.arsdigita.portal.Portlet; +import com.arsdigita.bebop.AbstractSingleSelectionModel; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.ComponentSelectionModel; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.GridPanel; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.List; +import com.arsdigita.bebop.list.ListModel; +import com.arsdigita.bebop.list.ListModelBuilder; +import com.arsdigita.bebop.list.ListCellRenderer; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.bebop.form.RadioGroup; +import com.arsdigita.bebop.form.Option; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.SimpleComponent; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.SplitWizard; +import com.arsdigita.bebop.SplitPanel; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.ChangeListener; +import com.arsdigita.bebop.event.ChangeEvent; +import com.arsdigita.bebop.event.RequestListener; +import com.arsdigita.bebop.event.RequestEvent; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.bebop.parameters.ParameterModel; +import com.arsdigita.portalserver.util.GlobalizationUtil; +import com.arsdigita.kernel.User; + +import org.apache.log4j.Category; + + +/** + * Experimental + * + * @author Jim Parsons + */ + +public final class PortalArchivePanel extends SplitPanel { + + List archiveList; + List onlineList; + + Label m_noPortalSelected; + + ArchiveForm archiveForm; + UnarchiveForm unarchiveForm; + + + static class ArchiveListModel implements ListModel { + PortalSiteCollection m_psites; + PortalSite m_currSite; + public ArchiveListModel() { + m_psites = PortalSite.retrieveAllPortalSites(); + m_psites.filterForArchived(); + } + public boolean next() { + if (!m_psites.next()) { + return false; + } + m_currSite = m_psites.getPortalSite(); + return true; + } + public Object getElement() { + return m_currSite; + } + public String getKey() { + return m_currSite.getID().toString(); + } + } + + static class OnlineListModel implements ListModel { + PortalSiteCollection m_psites; + PortalSite m_currSite; + public OnlineListModel() { + m_psites = PortalSite.retrieveAllPortalSites(); + m_psites.filterForUnarchived(); + } + public boolean next() { + if (!m_psites.next()) { + return false; + } + m_currSite = m_psites.getPortalSite(); + return true; + } + public Object getElement() { + return m_currSite; + } + public String getKey() { + return m_currSite.getID().toString(); + } + } + + + public PortalArchivePanel(Page p) { + + p.addRequestListener(new RequestListener () { + public void pageRequested(RequestEvent e) { + PageState ps = e.getPageState(); + if((!onlineList.isSelected(ps)) && + (!archiveList.isSelected(ps))) { + //neither list has a selection... + archiveForm.setVisible(ps,false); + unarchiveForm.setVisible(ps,false); + m_noPortalSelected.setVisible(ps, true); + } + } + }); + + setClassAttr("archiver"); + setDivider(40); + + GridPanel headerPanel = new GridPanel(1); + headerPanel.setClassAttr("archive_header"); + headerPanel.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.portal_archive_header"))); + setHeader(headerPanel); + + GridPanel portalPanel = new GridPanel(1); + portalPanel.setClassAttr("archive_panel"); + setLeftComponent(portalPanel); + + GridPanel formPanel = new GridPanel(1); + setRightComponent(formPanel); + + archiveList = new List( new ListModelBuilder() { + public ListModel makeModel(List l, PageState ps) { + return new ArchiveListModel(); + } + public void lock() {} + public boolean isLocked() { return true; } + }); + + archiveList.addChangeListener(new ChangeListener () { + public void stateChanged(ChangeEvent e) { + PageState ps = e.getPageState(); + archiveForm.setVisible(ps,false); + unarchiveForm.setVisible(ps, true); + m_noPortalSelected.setVisible(ps, false); + onlineList.clearSelection(ps); + } + }); + archiveList.setCellRenderer(new ArchiveListCellRenderer()); + archiveList.setClassAttr("archivelist"); + + Label emptyarchive = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.empty_archive")); + emptyarchive.setFontWeight(Label.ITALIC); + archiveList.setEmptyView(emptyarchive); + + onlineList = new List( new ListModelBuilder() { + public ListModel makeModel(List l, PageState ps) { + return new OnlineListModel(); + } + public void lock() {} + public boolean isLocked() { return true; } + }); + + onlineList.addChangeListener(new ChangeListener () { + public void stateChanged(ChangeEvent e) { + PageState ps = e.getPageState(); + archiveForm.setVisible(ps,true); + unarchiveForm.setVisible(ps, false); + m_noPortalSelected.setVisible(ps, false); + archiveList.clearSelection(ps); + } + }); + onlineList.setCellRenderer(new OnlineListCellRenderer()); + onlineList.setClassAttr("onlinelist"); + + Label emptyonline = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.empty_online")); + emptyonline.setFontWeight(Label.ITALIC); + onlineList.setEmptyView(emptyonline); + + Label onlinelabel = + new Label(GlobalizationUtil.globalize( + "cw.workspace.ui.admin.portals_currently_online")); + onlinelabel.setFontWeight(Label.BOLD); + portalPanel.add(onlinelabel); + portalPanel.add(onlineList); + + + Label archivelabel = + new Label(GlobalizationUtil.globalize( + "cw.workspace.ui.admin.portals_currently_archived")); + archivelabel.setFontWeight(Label.BOLD); + portalPanel.add(archivelabel); + portalPanel.add(archiveList); + + archiveForm = new ArchiveForm(); + formPanel.add(archiveForm); + + + unarchiveForm = new UnarchiveForm(); + formPanel.add(unarchiveForm); + + //set Default message in right pane when nothing selected + m_noPortalSelected = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.no_portal_selected")); + m_noPortalSelected.setFontWeight(Label.ITALIC); + formPanel.add(m_noPortalSelected); + + } + + public class ArchiveForm extends Form implements FormProcessListener { + private Label instruction; + private Submit button; + private Submit cancelbutton; + private RadioGroup radio; + private String recurse; + + public ArchiveForm() { + super("archiveform"); + instruction = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.archive_this_portal")); + button = new Submit(GlobalizationUtil.globalize("cw.workspace.ui.admin.archive")); + cancelbutton = new Submit(GlobalizationUtil.globalize("cw.workspace.ui.admin.cancel")); + radio = new RadioGroup("child_portals"); + radio.addOption(new Option("recurse",new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.recurse_archive")))); + this.add(instruction); + this.add(button); + this.add(cancelbutton); + this.add(radio); + this.addProcessListener(this); + } + + public void process(FormSectionEvent e) { + PageState s = e.getPageState(); + + if(button.isSelected(s)) { + recurse = (String)radio.getValue(s); + String id = (String)onlineList.getSelectedKey(s); + BigDecimal bd = new BigDecimal(id); + PortalSite p = PortalSite.retrievePortalSite(bd); + if(recurse == null) + p.archive(); + else + p.archiveRecurse(); + p.save(); + } + onlineList.clearSelection(s); + this.setVisible(s, false); + m_noPortalSelected.setVisible(s, true); + } + + public void init(FormSectionEvent e) throws FormProcessException { + PageState ps = e.getPageState(); + if((!onlineList.isSelected(ps)) && (!archiveList.isSelected(ps))) { + //neither list has a selection... + this.setVisible(ps,false); + m_noPortalSelected.setVisible(ps, true); + } + } + } + + public class UnarchiveForm extends Form implements FormProcessListener { + private Label instruction; + private Submit button; + private Submit cancelbutton; + + public UnarchiveForm() { + super("unarchiveform"); + instruction = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.online_this_portal")); + button = new Submit(GlobalizationUtil.globalize("cw.workspace.ui.admin.unarchive")); + cancelbutton = new Submit(GlobalizationUtil.globalize("cw.workspace.ui.admin.cancel")); + this.add(instruction); + this.add(button); + this.add(cancelbutton); + this.addProcessListener(this); + } + + public void process(FormSectionEvent e) { + PageState s = e.getPageState(); + + if(button.isSelected(s)) { + String id = (String)archiveList.getSelectedKey(s); + BigDecimal bd = new BigDecimal(id); + PortalSite p = PortalSite.retrievePortalSite(bd); + p.unarchive(); + p.save(); + } + archiveList.clearSelection(s); + this.setVisible(s, false); + m_noPortalSelected.setVisible(s, true); + } + + public void init(FormSectionEvent e) throws FormProcessException { + PageState ps = e.getPageState(); + if((!onlineList.isSelected(ps)) && (!archiveList.isSelected(ps))) { + //neither list has a selection... + this.setVisible(ps,false); + m_noPortalSelected.setVisible(ps, true); + } + } + } + + class OnlineListCellRenderer implements ListCellRenderer { + public Component getComponent(List list, PageState pageState, + Object value, String key, + int index, boolean isSelected) { + + String date; + String title; + PortalSite ps = (PortalSite)value; + if(ps instanceof PersonalPortal) { + PersonalPortal pvt = (PersonalPortal)ps; + User user = pvt.getOwningUser(); + title = user.getDisplayName() + " (personal)"; + } else { + title = ps.getTitle(); + } + SimpleDateFormat dft = new SimpleDateFormat(); + Date cd = ps.getCreationDate(); + //This null trap is for legacy portals + if(cd == null) + date = "----"; + else + date = dft.format(ps.getCreationDate()); + + if(isSelected) { + Label label = new Label(title); + label.setStyleAttr(date); + return label; + } + else { + ControlLink link = new ControlLink(title); + link.setStyleAttr(date); + return link; + } + } + } + + class ArchiveListCellRenderer implements ListCellRenderer { + public Component getComponent(List list, PageState pageState, + Object value, String key, + int index, boolean isSelected) { + + String title; + + PortalSite ps = (PortalSite)value; + if(ps instanceof PersonalPortal) { + PersonalPortal pvt = (PersonalPortal)ps; + User user = pvt.getOwningUser(); + title = user.getDisplayName() + " (personal)"; + } else { + title = ps.getTitle(); + } + SimpleDateFormat dft = new SimpleDateFormat(); + String d = dft.format(ps.getArchiveDate()); + if(isSelected) { + Label label = new Label(title); + label.setStyleAttr(d); + return label; + } + else { + ControlLink link = new ControlLink(title); + link.setStyleAttr(d); + return link; + } + } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalCreateDispatcher.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalCreateDispatcher.java new file mode 100644 index 000000000..4fb75f95c --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalCreateDispatcher.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.page.BebopMapDispatcher; +import com.arsdigita.ui.login.UserAuthenticationListener; + +import java.util.Map; +import java.util.HashMap; + +public class PortalCreateDispatcher extends BebopMapDispatcher { + + public static final String versionId = "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/admin/PortalCreateDispatcher.java#4 $ by $Author: dennis $, $DateTime: 2004/08/17 23:19:25 $"; + + public PortalCreateDispatcher() { + Map m = new HashMap(); + Page prtlCreatePage = new PortalCreatePage(); + + prtlCreatePage.addRequestListener(new UserAuthenticationListener()); + prtlCreatePage.lock(); + + m.put("", prtlCreatePage); + m.put("index", prtlCreatePage); + setMap(m); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalCreateForm.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalCreateForm.java new file mode 100644 index 000000000..727c40392 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalCreateForm.java @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import java.math.BigDecimal; + +import com.arsdigita.bebop.BoxPanel; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Tree; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.ParameterSingleSelectionModel; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.FormInitListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.PrintEvent; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.bebop.event.ParameterEvent; +import com.arsdigita.bebop.event.ParameterListener; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.bebop.form.TextArea; +import com.arsdigita.bebop.form.TextField; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.bebop.parameters.NotEmptyValidationListener; +import com.arsdigita.bebop.parameters.ParameterData; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.bebop.tree.TreeModel; +import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.Party; +import com.arsdigita.kernel.permissions.PermissionDescriptor; +import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; +import com.arsdigita.portal.Portlet; +import com.arsdigita.portalserver.ApplicationDirectoryPortlet; +import com.arsdigita.portalserver.PortalSite; +import com.arsdigita.portalserver.PortalNavigatorPortlet; +import com.arsdigita.portalserver.PortalSummaryPortlet; +import com.arsdigita.portalserver.PortalTab; +import com.arsdigita.web.Application; +import com.arsdigita.bebop.form.TextArea; +import org.apache.log4j.Logger; + +/** + *

    Form for initial Portal construction.

    + **/ +public class PortalCreateForm { + public static String versionId = "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/admin/PortalCreateForm.java#6 $ $Author: dennis $ $DateTime: 2004/08/17 23:19:25 $"; + + private static Logger s_log = Logger.getLogger(PortalCreateForm.class); + + /** + * @param parentPortal an input request local holding the parent of the + * portal to be created + * @param portalsiteRL the newly created portal will be set in the + * portalsiteRL RequestLocal + * @param onFinish will be run when creation of the portal is complete; + * the source of the action event will be the returned Component + * @return a component for portalsite creation given a parent portal */ + public static Component create(final RequestLocal parentPortalSite, + final RequestLocal portalsiteRL, + final ActionListener onFinish) { + + final Form portalCreation = new Form("portalcreation"); + portalCreation.setMethod(Form.POST); + + NotEmptyValidationListener notWhiteSpace = + new NotEmptyValidationListener(); + + UniquePortalURLValidationListener uniqueURL = + new UniquePortalURLValidationListener(); + + portalCreation.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.parent_workspace"))); + portalCreation.add(new Label(new PrintListener() { + public void prepare(PrintEvent e) { + PageState ps = e.getPageState(); + Label target = (Label) e.getTarget(); + PortalSite psite = (PortalSite) parentPortalSite.get(ps); + if (psite == null) { + target.setLabel( (String) GlobalizationUtil.globalize("cw.workspace.ui.admin.none").localize()); + target.setFontWeight(Label.ITALIC); + } else { + target.setLabel(psite.getDisplayName()); + } + } + })); + + final TextField psName = new TextField(new StringParameter("psName")); + psName.getParameterModel().addParameterListener(notWhiteSpace); + portalCreation.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.title"))); + portalCreation.add(psName); + + final TextField psLocation = + new TextField(new StringParameter("psNode")); + psLocation.getParameterModel().addParameterListener(notWhiteSpace); + psLocation.getParameterModel().addParameterListener(uniqueURL); + psLocation.getParameterModel().addParameterListener( + new ParameterListener() { + public void validate(ParameterEvent e) { + ParameterData data = e.getParameterData(); + String value = (String) data.getValue(); + char[] chars = value.toCharArray(); + for (int i = 0; i < chars.length; i++) { + if (!(Character.isLetterOrDigit(chars[i]) + || chars[i] == '-' || chars[i] == '_')) { + data.addError( "Can only contain letters, numbers, dashes, and underscores"); + break; + } + } + }}); + portalCreation.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.url_fragment"))); + portalCreation.add(psLocation); + + final TextArea psMission = + new TextArea(new StringParameter("psMission")); + portalCreation.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.mission"))); + portalCreation.add(psMission); + portalCreation.add(new Submit("done", "Create Portal")); + + portalCreation.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) + throws FormProcessException { + PageState ps = ev.getPageState(); + + PortalSite parent = (PortalSite) parentPortalSite.get(ps); + + String name = (String)psName.getValue(ps); + String location = (String)psLocation.getValue(ps); + String mission = (String)psMission.getValue(ps); + + PortalSite psite = PortalSite.createPortalSite + (location, name, parent); + psite.setMission(mission); + psite.save(); + + // By default, add some workspace portlets. + PortalTab mainTab = PortalTab.createTab("Main",psite); + + Portlet portlet = Portlet.createPortlet + (ApplicationDirectoryPortlet.BASE_DATA_OBJECT_TYPE, psite); + mainTab.addPortlet(portlet, 1); + + portlet = Portlet.createPortlet + (PortalNavigatorPortlet.BASE_DATA_OBJECT_TYPE, psite); + mainTab.addPortlet(portlet, 1); + + portlet = Portlet.createPortlet + (PortalSummaryPortlet.BASE_DATA_OBJECT_TYPE, psite); + mainTab.addPortlet(portlet, 1); +/* + Application DocRepositoryApp = Application.createApplication + (Repository.BASE_DATA_OBJECT_TYPE, "documents", + "My Document Manager", ws); + DocRepositoryApp.save(); + + portlet = Portlet.createPortlet + (RecentUpdatedDocsPortlet.BASE_DATA_OBJECT_TYPE, + DocRepositoryApp); + mainTab.addPortlet(portlet, 2); +*/ + mainTab.setPortalSite(psite); + mainTab.save(); + psite.addPortalTab(mainTab); + psite.save(); + + portalsiteRL.set(ps, psite); + + Party party = Kernel.getContext().getParty(); + + if (party == null) { + throw new IllegalStateException("not logged in"); + } + psite.addMember(party); + psite.save(); + PermissionDescriptor perm = new PermissionDescriptor + (PrivilegeDescriptor.ADMIN, psite, party); + PermissionService.grantPermission(perm); + + onFinish.actionPerformed + (new ActionEvent(portalCreation, ps)); + } + }); + + return portalCreation; + } + + /** + * @param portalsiteRL the newly created portalsite will be set in the + * portalsiteRL RequestLocal + * @param onFinish will be run when creation of the portal is complete; + * the source of the action event will be the returned Component + * @return a component for portal creation + **/ + public static Component create(final RequestLocal portalsiteRL, + final ActionListener onFinish) { + + final SimpleContainer retval = new SimpleContainer(); + + final Tree psParent = new Tree(new PortalTreeModelBuilder()); + psParent.setSelectionModel( new ParameterSingleSelectionModel( + new BigDecimalParameter("psParent"))); + + final Form parentSelection = new Form("parentselection", + new BoxPanel(BoxPanel.VERTICAL)); + parentSelection.setMethod(Form.POST); + + RequestLocal parentPortal = new RequestLocal() { + protected Object initialValue(PageState ps) { + BigDecimal id = (BigDecimal) psParent.getSelectedKey(ps); + if (id == null) { return null; } + return PortalSite.retrievePortalSite(id); + } + }; + + final Component portalCreation = PortalCreateForm.create( + parentPortal, portalsiteRL, new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState ps = e.getPageState(); + onFinish.actionPerformed(new ActionEvent(retval, ps)); + } + }); + + retval.add(parentSelection); + retval.add(portalCreation); + + parentSelection.addInitListener(new FormInitListener() { + public void init(FormSectionEvent e) { + PageState ps = e.getPageState(); + TreeModel tm = psParent.getTreeModel(ps); + portalCreation.setVisible(ps, false); + String key = (String) tm.getRoot(ps).getKey(); + if (psParent.isCollapsed(key, ps)) { + psParent.expand((String) tm.getRoot(ps).getKey(), ps); + } + } + }); + + parentSelection.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent e) { + PageState ps = e.getPageState(); + portalCreation.setVisible(ps, true); + parentSelection.setVisible(ps, false); + } + }); + + parentSelection.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.select_parent_workspace"))); + + psParent.setCellRenderer( + new PortalTreeModelBuilder.DefaultRenderer()); + + parentSelection.add(psParent); + + parentSelection.add(new Submit("Continue")); + + return retval; + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalCreatePage.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalCreatePage.java new file mode 100644 index 000000000..a71d8a63e --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalCreatePage.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.DimensionalNavbar; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; + +import com.arsdigita.portalserver.ApplicationPage; +import com.arsdigita.portalserver.PortalSite; + +class PortalCreatePage extends ApplicationPage { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/admin/PortalCreatePage.java#4 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + public PortalCreatePage() { + final RequestLocal portalsiteRL = new RequestLocal(); + + // TODO: parent portal selection after basic properties entered + final Component f = PortalCreateForm. + create(new RequestLocal(), portalsiteRL, new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState ps = e.getPageState(); + try { + com.arsdigita.dispatcher.DispatcherHelper.sendRedirect( + ps.getRequest(), ps.getResponse(), + ((PortalSite) portalsiteRL.get(ps)).getSiteNode().getURLNoContext() + "admin/"); + } catch (java.io.IOException ex) { + throw + new com.arsdigita.util.UncheckedWrapperException(ex); + } + } + }); + + add(f); + + } + + protected void buildContextBar() { + DimensionalNavbar navbar = new DimensionalNavbar(); + navbar.setClassAttr("portalNavbar"); + + navbar.add(new Link(new PersonalPortalLinkPrinter())); + navbar.add(new Link(new ParentApplicationLinkPrinter())); + navbar.add(new Label(new CurrentApplicationLabelPrinter())); + + getHeader().add(navbar); + } + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalCreator.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalCreator.java new file mode 100644 index 000000000..dd4cc3512 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalCreator.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + +import com.arsdigita.web.Application; +import com.arsdigita.persistence.*; +import org.apache.log4j.Logger; + +/** + * PortalCreator + * + * @author rhs@mit.edu + * @version $Revision: #5 $ $Date: 2004/08/17 $ + */ +public class PortalCreator extends Application { + public static final String versionId = + "$Id: //portalserver/dev/src/com/arsdigita/portalserver/ui/admin/PortalCreator.java#5 $" + + "$Author: dennis $" + + "$DateTime: 2004/08/17 23:19:25 $"; + + private static final Logger s_log = Logger.getLogger + (PortalCreator.class); + + public static final String BASE_DATA_OBJECT_TYPE = + "com.arsdigita.workspace.ui.WorkspaceCreator"; + + protected String getBaseDataObjectType() { + return BASE_DATA_OBJECT_TYPE; + } + + public PortalCreator(DataObject dataObject) { + super(dataObject); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalSiteMap.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalSiteMap.java new file mode 100644 index 000000000..a6ef2b8a5 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalSiteMap.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + +import com.arsdigita.web.Application; +import com.arsdigita.persistence.*; +import org.apache.log4j.Logger; + +/** + * PortalSiteMap + * + * @author Jim Parsons + */ +public class PortalSiteMap extends Application { + + private static final Logger s_log = Logger.getLogger + (PortalSiteMap.class); + + public static final String BASE_DATA_OBJECT_TYPE = + "com.arsdigita.workspace.ui.PortalSiteMap"; + + protected String getBaseDataObjectType() { + return BASE_DATA_OBJECT_TYPE; + } + + public PortalSiteMap(DataObject dataObject) { + super(dataObject); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalSiteMapDispatcher.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalSiteMapDispatcher.java new file mode 100644 index 000000000..b9d7c775f --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalSiteMapDispatcher.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageFactory; +//import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.page.BebopMapDispatcher; +import com.arsdigita.ui.login.UserAuthenticationListener; + +//import java.util.Map; +//import java.util.HashMap; +import org.apache.log4j.Logger; + +/** + * XXX JAVADOC + * + */ +public class PortalSiteMapDispatcher extends BebopMapDispatcher { + + private static final Logger s_log = Logger.getLogger + (PortalSiteMapDispatcher.class); + + private static final String XSL_HOOK = "portal-sitemap"; + + + /** + * + */ + public PortalSiteMapDispatcher() { + s_log.info("PortalSiteMapDispatcher created!"); + + Page index = buildSiteMapPage(); + addPage("", index); + addPage("index.jsp", index); + } + + /** + * + * @return + */ + static Page buildSiteMapPage() { + Page page = PageFactory.buildPage(XSL_HOOK, "Portal Site Map"); + PortalSiteMapPanel sitemapPanel = new PortalSiteMapPanel(page); + page.add(sitemapPanel); + page.addRequestListener(new UserAuthenticationListener()); + + page.lock(); + return page; + } + +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalSiteMapPanel.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalSiteMapPanel.java new file mode 100644 index 000000000..66a3ddd8f --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalSiteMapPanel.java @@ -0,0 +1,1059 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; +import java.util.Date; +import java.text.SimpleDateFormat; +import com.arsdigita.portalserver.PortalSite; +import com.arsdigita.portalserver.PortalSiteCollection; +import com.arsdigita.portalserver.PortalPage; +import com.arsdigita.portalserver.personal.PersonalPortal; +import com.arsdigita.portal.Portlet; +import com.arsdigita.web.Application; +import com.arsdigita.web.ApplicationCollection; +import com.arsdigita.web.ApplicationType; +import com.arsdigita.bebop.AbstractSingleSelectionModel; +import com.arsdigita.bebop.Container; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.ComponentSelectionModel; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.GridPanel; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.List; +import com.arsdigita.bebop.list.ListModel; +import com.arsdigita.bebop.list.ListModelBuilder; +import com.arsdigita.bebop.list.ListCellRenderer; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.event.PrintEvent; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.bebop.form.RadioGroup; +import com.arsdigita.bebop.form.CheckboxGroup; +import com.arsdigita.bebop.form.Option; +import com.arsdigita.bebop.form.TextField; +import com.arsdigita.bebop.form.TextArea; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.parameters.NotNullValidationListener; +import com.arsdigita.bebop.parameters.NotEmptyValidationListener; +import com.arsdigita.bebop.parameters.ArrayParameter; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.SimpleComponent; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.SplitWizard; +import com.arsdigita.bebop.SplitPanel; +import com.arsdigita.bebop.Tree; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.ChangeListener; +import com.arsdigita.bebop.event.ChangeEvent; +import com.arsdigita.bebop.event.RequestListener; +import com.arsdigita.bebop.event.RequestEvent; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.bebop.parameters.ParameterModel; +import com.arsdigita.portalserver.util.GlobalizationUtil; +import com.arsdigita.kernel.User; +import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.KernelExcursion; +import com.arsdigita.xml.Element; + +import org.apache.log4j.Category; + + +/** + * This Class aggregates common admin utilities in one page. + * @author Jim Parsons + */ + +public final class PortalSiteMapPanel extends SplitPanel { + + + Tree m_portalTree; + PortalTreeModelBuilder m_portalTreeModelBuilder; + Label m_noPortalSelected; + ArchiveForm archiveForm; + UnarchiveForm unarchiveForm; + PropertiesForm propForm; + EditPropertiesForm editpropForm; + DeleteForm deleteform; + Component createform; + Component createchildform; + GridPanel vmdPanel; //view, modify, delete + GridPanel linkPanel; + RequestLocal m_selectedPortalRL; + RequestLocal portalsiteRL; + RequestLocal childportalsiteRL; + + + + public PortalSiteMapPanel(Page p) { + + p.addRequestListener(new RequestListener () { + public void pageRequested(RequestEvent e) { + PageState s = e.getPageState(); + if(!m_portalTree.isSelected(s)) { + //Site map Tree does not have a selection... + //set all forms invisible + clearAllVisibility(s); + linkPanel.setVisible(s,true); + m_noPortalSelected.setVisible(s, true); + } + } + }); + + portalsiteRL = new RequestLocal(); + childportalsiteRL = new RequestLocal(); + + m_selectedPortalRL = new RequestLocal() { + protected Object initialValue(PageState s) { + if(m_portalTree.isSelected(s)) { + String portalIDstr = + (String)m_portalTree.getSelectionModel() + .getSelectedKey(s); + return + PortalSite.retrievePortalSite(new BigDecimal(portalIDstr)); + } else { + return null; + } + } + }; + + + setClassAttr("portalsitemap"); + setDivider(40); + + GridPanel headerPanel = new GridPanel(1); + headerPanel.setClassAttr("portalsitemap_header"); + headerPanel.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.portal_archive_header"))); + setHeader(headerPanel); + + GridPanel portalPanel = new GridPanel(1); + portalPanel.setClassAttr("portalsitemap_panel"); + setLeftComponent(portalPanel); + + GridPanel RHSPanel = new GridPanel(1); + GridPanel formPanel = new GridPanel(1); + GridPanel actionPanel = new GridPanel(1); + linkPanel = new GridPanel(4); + linkPanel.setClassAttr("portalsitemaplinkpanel"); + setRightComponent(RHSPanel); + RHSPanel.add(formPanel); + RHSPanel.add(actionPanel); + + archiveForm = new ArchiveForm(); + actionPanel.add(archiveForm); + + unarchiveForm = new UnarchiveForm(); + actionPanel.add(unarchiveForm); + + GridPanel gp0 = new GridPanel(1); + gp0.setClassAttr("deleteform"); + deleteform = new DeleteForm(gp0); + actionPanel.add(deleteform); + + actionPanel.add(linkPanel); + + GridPanel gp1 = new GridPanel(1); + gp1.setClassAttr("propertiesform"); + propForm = new PropertiesForm(gp1); + formPanel.add(propForm); + + GridPanel gp2 = new GridPanel(1); + gp2.setClassAttr("editpropscontainer"); + editpropForm = new EditPropertiesForm(gp2); + formPanel.add(editpropForm); + + + //this panel exists so view, modify, and delete can be + //optionally visible + vmdPanel = new GridPanel(3) { + public boolean isVisible(PageState s) { + if(m_portalTree.isSelected(s)) + return(true); + else + return(false); + } + }; + vmdPanel.setClassAttr("portalsitemaplinkpanelvmd"); + linkPanel.add(vmdPanel); + + createform = PortalCreateForm.create(new RequestLocal(), + portalsiteRL, new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState s = e.getPageState(); + //turn off this form and turn on completion form + } + }); + formPanel.add(createform); + + createchildform = PortalCreateForm.create(m_selectedPortalRL, + childportalsiteRL, new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState s = e.getPageState(); + //turn off this form and turn on completion form + } + }); + + formPanel.add(createchildform); + + m_portalTreeModelBuilder = new PortalTreeModelBuilder(false); + + m_portalTree = new Tree( m_portalTreeModelBuilder); + + m_portalTree.addChangeListener(new ChangeListener () { + public void stateChanged(ChangeEvent e) { + PageState s = e.getPageState(); + if(m_portalTree.isSelected(s)) { + clearAllVisibility(s); + propForm.setVisible(s, true); + linkPanel.setVisible(s, true); + vmdPanel.setVisible(s, true); + } else { + clearAllVisibility(s); + m_noPortalSelected.setVisible(s, true); + } + + } + }); + m_portalTree.setCellRenderer + (new PortalTreeModelBuilder.DefaultRenderer()); + m_portalTree.setClassAttr("portalsitemap_tree"); + + Label sitemaplabel = + new Label(GlobalizationUtil.globalize( + "cw.workspace.ui.admin.portals_currently_mounted")); + sitemaplabel.setFontWeight(Label.BOLD); + portalPanel.add(sitemaplabel); + portalPanel.add(m_portalTree); + + + //////////////////////////////// + //Set up links in link panel. + /////////////////////////////// + + //////////////////////////////// + //Create panel links + + //Link for creating top level workplaces + ActionLink createtoplevel = + new ActionLink(new Label(GlobalizationUtil. + globalize("cw.workspace.ui.admin.create_top_level"))); + createtoplevel.setClassAttr("createtoplevel"); + createtoplevel.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState s = e.getPageState(); + if(m_portalTree.isSelected(s)) { + PortalSite psite = (PortalSite)m_selectedPortalRL.get(s); + if(psite != null) { + clearAllVisibility(s); + createform.setVisible(s,true); + } + } + } + }); + + //Link for creating child portals, only visible when + //a portal is selected in tree widget. + ActionLink createchild = + new ActionLink(new Label(GlobalizationUtil. + globalize("cw.workspace.ui.admin.create_child"))) { + public boolean isVisible(PageState s) { + if(m_portalTree.isSelected(s)) + return(true); + else + return(false); + } + }; + createchild.setClassAttr("createchild"); + createchild.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState s = e.getPageState(); + if(m_portalTree.isSelected(s)) { + PortalSite psite = (PortalSite)m_selectedPortalRL.get(s); + if(psite != null) { + clearAllVisibility(s); + createchildform.setVisible(s,true); + } + } + } + }); + Label createPanelLabel = + new Label(GlobalizationUtil. + globalize("cw.workspace.ui.admin.create")); + createPanelLabel.setIdAttr("createpanelheader"); + linkPanel.add(createPanelLabel); + linkPanel.add(createtoplevel); + linkPanel.add(createchild); + + ////////////////////////// + //View panel links + + //Visit in new browser window + Link visitbutton = new Link("Visit selected portal",""); + visitbutton.setClassAttr("portalvisitlink"); + try { + visitbutton.addPrintListener(new PrintListener() { + public void prepare(PrintEvent e) { + PageState s = e.getPageState(); + //Check if portal is selected + if(m_portalTree.isSelected(s)) { + PortalSite psite = (PortalSite)m_selectedPortalRL.get(s); + Link l = (Link)e.getTarget(); + if(!(psite == null)) { + l.setTarget(psite.getPath()); + } else { + l.setTarget(""); + } + } + } + }); + } catch(java.util.TooManyListenersException e) { } + + //Visit local admin in new browser window + Link visitadminbutton = + new Link("Visit selected portal admin page",""); + visitadminbutton.setClassAttr("portaladminvisitlink"); + try { + visitadminbutton.addPrintListener(new PrintListener() { + public void prepare(PrintEvent e) { + PageState s = e.getPageState(); + //Check if portal is selected + if(m_portalTree.isSelected(s)) { + PortalSite psite = (PortalSite)m_selectedPortalRL.get(s); + Link l = (Link)e.getTarget(); + if(!(psite == null)) { + l.setTarget(psite.getPath() + "/admin/"); + } else { + l.setTarget(""); + } + } + } + }); + + } catch(java.util.TooManyListenersException e) { } + + Label viewLabel = + new Label(GlobalizationUtil. + globalize("cw.workspace.ui.admin.viewpanel_header")); + viewLabel.setIdAttr("viewpanelheader"); + vmdPanel.add(viewLabel); + vmdPanel.add(visitbutton); + vmdPanel.add(visitadminbutton); + + //////////////////////// + //Modify Panel links + + Label archivelinklabel = new Label("Archive/Unarchive"); + archivelinklabel.addPrintListener(new PrintListener() { + public void prepare(PrintEvent e) { + PageState s = e.getPageState(); + Label t = (Label)e.getTarget(); + if(m_portalTree.isSelected(s)) { + PortalSite psite = (PortalSite)m_selectedPortalRL.get(s); + if(!(psite == null)) { + if(psite.isArchived()) + t.setLabel(GlobalizationUtil. + globalize("cw.workspace.ui.admin.unarchive")); + else + t.setLabel(GlobalizationUtil. + globalize("cw.workspace.ui.admin.archive")); + } + } + } + }); + + + + ActionLink archivebutton = new ActionLink(archivelinklabel); + archivebutton.setClassAttr("portalarchivelink"); + archivebutton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState s = e.getPageState(); + if(m_portalTree.isSelected(s)) { + PortalSite psite = (PortalSite)m_selectedPortalRL.get(s); + if(psite != null) { + if(psite.isArchived()) { + clearAllVisibility(s); + unarchiveForm.setVisible(s, true); + propForm.setVisible(s, true); + } else { + clearAllVisibility(s); + archiveForm.setVisible(s, true); + propForm.setVisible(s, true); + } + } + } + } + }); + + Label modifyLabel = + new Label(GlobalizationUtil. + globalize("cw.workspace.ui.admin.modifypanel_header")); + modifyLabel.setIdAttr("modifypanelheader"); + vmdPanel.add(modifyLabel); + vmdPanel.add(archivebutton); + + ////////////////////// + //Delete links + ActionLink deletebutton = new ActionLink("Delete"); + deletebutton.setClassAttr("portaldeletelink"); + deletebutton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState s = e.getPageState(); + //Set delete form visible + clearAllVisibility(s); + deleteform.setVisible(s, true); + propForm.setVisible(s, true); + } + }); + + Label deleteLabel = + new Label(GlobalizationUtil. + globalize("cw.workspace.ui.admin.deletepanel_header")); + deleteLabel.setIdAttr("deletepanelheader"); + vmdPanel.add(deleteLabel); + vmdPanel.add(deletebutton); + + //set Default message in right pane when nothing selected + m_noPortalSelected = + new Label(GlobalizationUtil + .globalize("cw.workspace.ui.admin.no_portal_selected")); + m_noPortalSelected.setFontWeight(Label.ITALIC); + formPanel.add(m_noPortalSelected); + + + } + + /** + * Set's all relevant panels and forms to no visibility. + * + */ + public void clearAllVisibility(PageState s) { + propForm.setVisible(s, false); + editpropForm.setVisible(s, false); + createform.setVisible(s,false); + createchildform.setVisible(s,false); + linkPanel.setVisible(s, false); + vmdPanel.setVisible(s, false); + archiveForm.setVisible(s,false); + unarchiveForm.setVisible(s, false); + deleteform.setVisible(s, false); + m_noPortalSelected.setVisible(s, false); + } + + + public class ArchiveForm extends Form implements FormProcessListener { + private Label instruction; + private Submit button; + private Submit cancelbutton; + private RadioGroup radio; + private String recurse; + + public ArchiveForm() { + super("archiveform"); + instruction = new Label(GlobalizationUtil + .globalize("cw.workspace.ui.admin.archive_this_portal")); + button = new Submit(GlobalizationUtil + .globalize("cw.workspace.ui.admin.archive")); + cancelbutton = new Submit(GlobalizationUtil + .globalize("cw.workspace.ui.admin.cancel")); + radio = new RadioGroup("child_portals"); + radio.addOption(new Option("recurse",new Label(GlobalizationUtil + .globalize("cw.workspace.ui.admin.recurse_archive")))); + this.add(instruction); + this.add(button); + this.add(cancelbutton); + this.add(radio); + this.addProcessListener(this); + } + + public void process(FormSectionEvent e) { + PageState s = e.getPageState(); + + if(button.isSelected(s)) { + recurse = (String)radio.getValue(s); + String id = (String)m_portalTree.getSelectedKey(s); + BigDecimal bd = new BigDecimal(id); + PortalSite p = PortalSite.retrievePortalSite(bd); + if(recurse == null) + p.archive(); + else + p.archiveRecurse(); + p.save(); + } + m_portalTree.clearSelection(s); + this.setVisible(s, false); + m_noPortalSelected.setVisible(s, true); + } + + } + + + public class UnarchiveForm extends Form implements FormProcessListener { + private Label instruction; + private Submit button; + private Submit cancelbutton; + + public UnarchiveForm() { + super("unarchiveform"); + instruction = new Label(GlobalizationUtil + .globalize("cw.workspace.ui.admin.online_this_portal")); + button = new Submit(GlobalizationUtil + .globalize("cw.workspace.ui.admin.unarchive")); + cancelbutton = new Submit(GlobalizationUtil + .globalize("cw.workspace.ui.admin.cancel")); + this.add(instruction); + this.add(button); + this.add(cancelbutton); + this.addProcessListener(this); + } + + public void process(FormSectionEvent e) { + PageState s = e.getPageState(); + + if(button.isSelected(s)) { + String id = (String)m_portalTree.getSelectedKey(s); + BigDecimal bd = new BigDecimal(id); + PortalSite p = PortalSite.retrievePortalSite(bd); + p.unarchive(); + p.save(); + } + m_portalTree.clearSelection(s); + this.setVisible(s, false); + m_noPortalSelected.setVisible(s, true); + } + + } + + + public class PropertiesForm extends Form { + private Label nameSelected; + + private Label nameLabel; + private Label name; + + private Label urlLabel; + private Label url; + + private Label descriptionLabel; + private Label description; + + private Label creationDateLabel; + private Label creationDate; + + private Label statusLabel; + private Label status; + + private Label membersLabel; + private List members; + + private Label applications; + private List apps; + + private ActionLink editlink; + + + + + public PropertiesForm(GridPanel gp) { + super("propsform", gp); + + nameSelected = new Label("Selected Portal"); + nameSelected.setIdAttr("propnameselected"); + nameSelected.addPrintListener(new PrintListener() { + public void prepare(PrintEvent e) { + PageState s = e.getPageState(); + if(m_portalTree.isSelected(s)) { + PortalSite psite = (PortalSite)m_selectedPortalRL.get(s); + if(!(psite == null)) { + String n = psite.getDisplayName(); + Label t = (Label)e.getTarget(); + t.setLabel(GlobalizationUtil + .globalize("cw.workspace.ui.admin.props") + .localize(s.getRequest()) + " " + n); + } + } + } + }); + + this.add(nameSelected); + this.add(new Label("")); + + nameLabel = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.portal_name")); + nameLabel.setIdAttr("propnamelabel"); + + name = new Label("portalname"); + name.setIdAttr("propname"); + + name.addPrintListener(new PrintListener() { + public void prepare(PrintEvent e) { + PageState s = e.getPageState(); + if(m_portalTree.isSelected(s)) { + PortalSite psite = (PortalSite)m_selectedPortalRL.get(s); + if(!(psite == null)) { + String n = psite.getDisplayName(); + Label t = (Label)e.getTarget(); + t.setLabel(n); + } + } + } + }); + + this.add(nameLabel); + this.add(name); + + urlLabel = new Label(GlobalizationUtil + .globalize("cw.workspace.ui.admin.portal_url")); + urlLabel.setIdAttr("propurllabel"); + + url = new Label("portalurl"); + url.setIdAttr("propurl"); + url.addPrintListener(new PrintListener() { + public void prepare(PrintEvent e) { + PageState s = e.getPageState(); + if(m_portalTree.isSelected(s)) { + PortalSite psite = (PortalSite)m_selectedPortalRL.get(s); + if(!(psite == null)) { + String n = psite.getPath(); + Label t = (Label)e.getTarget(); + t.setLabel(n); + } + } + } + }); + + this.add(urlLabel); + this.add(url); + + descriptionLabel = new Label(GlobalizationUtil + .globalize("cw.workspace.ui.admin.portal_desc")); + descriptionLabel.setIdAttr("propdescriptionlabel"); + + description = new Label("portaldesc"); + description.setIdAttr("propdescription"); + description.addPrintListener(new PrintListener() { + public void prepare(PrintEvent e) { + PageState s = e.getPageState(); + if(m_portalTree.isSelected(s)) { + PortalSite psite = (PortalSite)m_selectedPortalRL.get(s); + if(!(psite == null)) { + String n = psite.getMission(); + Label t = (Label)e.getTarget(); + t.setLabel(n); + } + } + } + }); + + this.add(descriptionLabel); + this.add(description); + + creationDateLabel = new Label(GlobalizationUtil + .globalize("cw.workspace.ui.admin.portal_creation_date")); + creationDateLabel.setIdAttr("propcreationdatelabel"); + + creationDate = new Label("portalcreation"); + creationDate.setIdAttr("propcreationdate"); + creationDate.addPrintListener(new PrintListener() { + public void prepare(PrintEvent e) { + PageState s = e.getPageState(); + if(m_portalTree.isSelected(s)) { + PortalSite psite = (PortalSite)m_selectedPortalRL.get(s); + if(!(psite == null)) { + Date d = psite.getCreationDate(); + SimpleDateFormat dft = new SimpleDateFormat(); + String date; + //This null trap is for legacy portals + if(d == null) + date = "----"; + else + date = dft.format(d); + Label t = (Label)e.getTarget(); + t.setLabel(date); + } + } + } + }); + + this.add(creationDateLabel); + this.add(creationDate); + + statusLabel = new Label(GlobalizationUtil + .globalize("cw.workspace.ui.admin.portal_status")); + statusLabel.setIdAttr("propstatuslabel"); + + status = new Label("portalstatus"); + status.setIdAttr("propstatus"); + status.addPrintListener(new PrintListener() { + public void prepare(PrintEvent e) { + PageState s = e.getPageState(); + if(m_portalTree.isSelected(s)) { + PortalSite psite = (PortalSite)m_selectedPortalRL.get(s); + if(!(psite == null)) { + Label t = (Label)e.getTarget(); + if(psite.isDraft()) { + t.setLabel(GlobalizationUtil + .globalize("cw.workspace.ui.admin.is_draft")); + } else { + if(psite.isArchived()) { + Date d = psite.getArchiveDate(); + SimpleDateFormat dft = new SimpleDateFormat(); + t.setLabel(GlobalizationUtil + .globalize("cw.workspace.ui.admin.is_archived") + .localize(s.getRequest()) + + " " + dft.format(d)); + } else { + t.setLabel(GlobalizationUtil + .globalize("cw.workspace.ui.admin.is_online")); + } + } + + } + } + } + }); + + this.add(statusLabel); + this.add(status); + + editlink = new ActionLink("Edit These Properties"); + editlink.setIdAttr("propedittheseprops"); + editlink.addActionListener( new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState s = e.getPageState(); + editpropForm.setVisible(s, true); + propForm.setVisible(s, false); + linkPanel.setVisible(s, false); + } + }); + + this.add(editlink); + + } + + } + + public class EditPropertiesForm extends Form implements FormProcessListener { + + private Label heading; + + private Label nameLabel; + private TextField name; + + private Label descriptionLabel; + private TextArea description; + + private Submit update; + private Submit cancel; + + EditPropertiesForm(GridPanel gp) { + super("editpropsform", gp); + + heading = new Label("Editable Properties"); + heading.setIdAttr("editpropnameselected"); + heading.addPrintListener(new PrintListener() { + public void prepare(PrintEvent e) { + PageState s = e.getPageState(); + if(m_portalTree.isSelected(s)) { + PortalSite psite = (PortalSite)m_selectedPortalRL.get(s); + if(!(psite == null)) { + String n = psite.getDisplayName(); + Label t = (Label)e.getTarget(); + t.setLabel(GlobalizationUtil + .globalize("cw.workspace.ui.admin.edit_props") + .localize(s.getRequest()) + " " + n); + } + } + } + }); + + this.add(heading); + + nameLabel = + new Label(GlobalizationUtil. + globalize("cw.workspace.ui.admin.portal_name")); + nameLabel.setIdAttr("editpropnamelabel"); + + name = new TextField("portalname"); + name.setIdAttr("editpropname"); + name.addValidationListener( + new NotNullValidationListener(GlobalizationUtil + .globalize("cw.workspace.ui.admin.need_portal_name"))); + + try { + name.addPrintListener(new PrintListener() { + public void prepare(PrintEvent e) { + PageState s = e.getPageState(); + if(m_portalTree.isSelected(s)) { + PortalSite psite = (PortalSite)m_selectedPortalRL.get(s); + if(!(psite == null)) { + String n = psite.getDisplayName(); + TextField tf = (TextField)e.getTarget(); + tf.setValue(s, n); + } + } + } + }); + } catch(java.util.TooManyListenersException e) { } + + this.add(nameLabel); + this.add(name); + + descriptionLabel = new Label(GlobalizationUtil + .globalize("cw.workspace.ui.admin.portal_desc")); + descriptionLabel.setIdAttr("editpropdescriptionlabel"); + + description = new TextArea("portaldesc"); + description.setIdAttr("editpropdescription"); + try { + description.addPrintListener(new PrintListener() { + public void prepare(PrintEvent e) { + PageState s = e.getPageState(); + if(m_portalTree.isSelected(s)) { + PortalSite psite = (PortalSite)m_selectedPortalRL.get(s); + if(!(psite == null)) { + String n = psite.getMission(); + TextArea ta = (TextArea)e.getTarget(); + ta.setValue(s, n); + } + } + } + }); + } catch(java.util.TooManyListenersException e) { } + + this.add(descriptionLabel); + this.add(description); + + update = new Submit(GlobalizationUtil + .globalize("cw.workspace.ui.admin.update")); + update.setIdAttr("editproptextinput"); + + cancel = new Submit(GlobalizationUtil + .globalize("cw.workspace.ui.admin.cancel")); + cancel.setIdAttr("editproptextcancel"); + + add(update); + add(cancel); + addProcessListener(this); + + + } + + public void process(FormSectionEvent e) { + PageState s = e.getPageState(); + + if(update.isSelected(s)) { + PortalSite psite = (PortalSite)m_selectedPortalRL.get(s); + if(!(psite == null)) { + //Set props, then save + String pname = (String)name.getValue(s); + psite.setTitle(pname); + String pdesc = (String)description.getValue(s); + psite.setMission(pdesc); + psite.save(); + } + } + clearAllVisibility(s); + propForm.setVisible(s, true); + linkPanel.setVisible(s, true); + vmdPanel.setVisible(s, true); + } + } + + + public class DeleteForm extends Form implements FormProcessListener { + private Label instruction3; + private Label instruction1; + private Label deleteTableHeader1; + private Label deleteTableHeader2; + private Label deleteTableHeader3; + private Submit button; + private Submit cancelbutton; + PortalSite psite; + PageState s; + CheckboxGroup checkGroup; + List list; + ArrayParameter params; + private final static String APP_LIST = "delete-form-app-choices"; + + public DeleteForm(GridPanel gp) { + super("deleteform", gp); + + params = new ArrayParameter(new BigDecimalParameter(APP_LIST)); + checkGroup = new CheckboxGroup(APP_LIST); + + list = new List(new ListModelBuilder() { + public ListModel makeModel(List l, PageState s) { + PortalSite psite = (PortalSite)m_selectedPortalRL.get(s); + return new AppListModel(psite); + } + public void lock() {} + public boolean isLocked() {return true; } + }); + list.setIdAttr("deleteappslist"); + list.setCellRenderer(new ListCellRenderer() { + public Component getComponent(List l, PageState s, Object value, + String key, int index, boolean isSelected) { + + SimpleContainer container = new SimpleContainer(); + container.setIdAttr("deleteapplist"); + Label type = null; + Option newOption = new Option(key, ""); + newOption.setGroup(checkGroup); + Label name = new Label((String)value); + name.setIdAttr("deleteappname"); + Application app = Application.retrieveApplication(new + BigDecimal(key)); + if(!(app == null)) { + type = new Label(app.getApplicationType().getTitle()); + type.setIdAttr("deleteapptype"); + } + container.add(newOption); + container.add(name); + if(type != null) + container.add(type); + + return container; + } + }); + + deleteTableHeader1 = + new Label(GlobalizationUtil.globalize + ("cw.workspace.ui.admin.delete_table_header1")); + deleteTableHeader1.setIdAttr("deletetableheader1"); + + deleteTableHeader2 = + new Label(GlobalizationUtil.globalize + ("cw.workspace.ui.admin.delete_table_header2")); + deleteTableHeader2.setIdAttr("deletetableheader2"); + + deleteTableHeader3 = + new Label(GlobalizationUtil.globalize + ("cw.workspace.ui.admin.delete_table_header3")); + deleteTableHeader3.setIdAttr("deletetableheader3"); + + instruction1 = + new Label(GlobalizationUtil.globalize + ("cw.workspace.ui.admin.delete_instruction1")); + instruction1.setIdAttr("delete_instruction1"); + + instruction3 = + new Label(GlobalizationUtil.globalize + ("cw.workspace.ui.admin.delete_this_portal")); + instruction3.setIdAttr("delete_instruction3"); + + button = + new Submit(GlobalizationUtil.globalize + ("cw.workspace.ui.admin.delete")); + button.setIdAttr("deleteformbutton"); + cancelbutton = + new Submit(GlobalizationUtil + .globalize("cw.workspace.ui.admin.cancel")); + cancelbutton.setIdAttr("deleteformcancelbutton"); + + this.add(instruction1); + this.add(instruction3); + this.add(deleteTableHeader1); + this.add(deleteTableHeader2); + this.add(deleteTableHeader3); + this.add(new Label("")); + this.add(button); + this.add(cancelbutton); + this.add(checkGroup); + this.add(list); + this.addProcessListener(this); + } + + public void register(Page p) { + super.register(p); + p.addComponentStateParam(this, params); + } + + public void process(FormSectionEvent e) { + s = e.getPageState(); + + if(button.isSelected(s)) { + KernelExcursion ex = new KernelExcursion() { + protected void excurse() { + Application deadApp; + //This string array contains IDs of apps user wishes deleted + String[] selectedApps = + (String[])checkGroup.getValue(s); + if(selectedApps != null) { + for( int i = 0; i < selectedApps.length; i++) { + deadApp = + Application.retrieveApplication(new BigDecimal + (selectedApps[i])); + deadApp.delete(); + } + } + psite = (PortalSite)m_selectedPortalRL.get(s); + setEffectiveParty(Kernel.getSystemParty()); + psite.delete(); + } + }; + ex.run(); + + clearAllVisibility(s); + m_portalTree.clearSelection(s); + this.setVisible(s, false); + m_noPortalSelected.setVisible(s, true); + linkPanel.setVisible(s, true); + } else { + clearAllVisibility(s); + this.setVisible(s, false); + propForm.setVisible(s, true); + linkPanel.setVisible(s, true); + vmdPanel.setVisible(s, true); + } + } + //------------------------------------------------------------ + public class AppListModel implements ListModel { + ApplicationCollection m_apps; + Application m_app; + public AppListModel(PortalSite psite) { + m_apps = psite.getFullPagePortalSiteApplications(); + } + public boolean next() { + if (!m_apps.next()) { + return false; + } + m_app = m_apps.getApplication(); + return true; + } + public Object getElement() { + return m_app.getTitle(); + } + public String getKey() { + return m_app.getID().toString(); + } + } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalTreeModelBuilder.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalTreeModelBuilder.java new file mode 100644 index 000000000..b74e7b82d --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortalTreeModelBuilder.java @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import java.math.BigDecimal; + +import java.util.Iterator; + +import com.arsdigita.portalserver.PortalSite; +import com.arsdigita.portalserver.PortalSiteCollection; + +import com.arsdigita.util.LockableImpl; + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SimpleContainer; + +import com.arsdigita.bebop.Tree; +import com.arsdigita.bebop.tree.TreeCellRenderer; +import com.arsdigita.bebop.tree.TreeModel; +import com.arsdigita.bebop.tree.TreeModelBuilder; +import com.arsdigita.bebop.tree.TreeNode; + +import com.arsdigita.domain.DomainCollectionIterator; +import org.apache.log4j.Logger; + +/** + *

    TreeModelBuilder for Portal Site hierarchies. + * This Class will work in two different modes by setting + * the internal boolean class var. This can be done during + * construction or via a setter method. A true value + * filters PortalSites to include only those that + * are online. This mode is helpful for typical user UI. + * If the value is set to false, then all Portal Sites, + * including those that are archived and in Draft status, are + * included in the tree model. This mode is useful for admin UI. + *

    + **/ +public class PortalTreeModelBuilder + extends LockableImpl + implements TreeModelBuilder { + + private static final Logger s_log = Logger.getLogger(PortalTreeModelBuilder.class); + + + private BigDecimal m_rootId; + private boolean m_filterPSites; + + + /** + *

    Construct a new PortalTreeModelBuilder whose root is the + * toplevel portal.

    + **/ + public PortalTreeModelBuilder() { + this(null, true); + } + + public PortalTreeModelBuilder(boolean filterPSites) { + this(null, filterPSites); + } + + /** + *

    Construct a new PortalTreeModelBuilder whose root is the + * portal with the specified ID.

    + **/ + public PortalTreeModelBuilder(BigDecimal rootprtlId) { + m_rootId = rootprtlId; + m_filterPSites = true; + } + + public PortalTreeModelBuilder(BigDecimal rootprtlId, boolean filterPSites) { + m_rootId = rootprtlId; + m_filterPSites = filterPSites; + } + + + /** + *

    Get the ID of the portal at which the tree built by this + * ModelBuilder will be rooted.

    + **/ + public BigDecimal getRootID() { + return m_rootId; + } + + /** + *

    Get the filter mode value for + * this ModelBuilder.

    + **/ + public boolean getFilterPSites() { + return m_filterPSites; + } + + /** + *

    Set the filter mode value for + * this ModelBuilder. Setting this value + * to false results in the TreeModel + * including ALL PortalSites in the system: Archived + * and Draft versions as well as online Portal Sites. + * A true value for this parameter filters PortalSite + * collections to include only online Portal Sites.

    + **/ + public void setFilterPSites(boolean filterPSites) { + m_filterPSites = filterPSites; + } + + public TreeModel makeModel(Tree t, PageState s) { + + return new TreeModel() { + + public Iterator getChildren(TreeNode n, PageState ps) { + PortalSite psite = (PortalSite)n.getElement(); + final PortalSiteCollection psc; + + if (psite == null) { + if(m_filterPSites) + psc = PortalSite.getRootPortalSites(); + else + psc = PortalSite.getAllRootPortalSites(); + } else { + if(m_filterPSites) + psc = psite.getChildPortalSites(); + else + psc = psite.getAllChildPortalSites(); + } + + final DomainCollectionIterator dci = + new DomainCollectionIterator(psc); + + return new Iterator() { + public boolean hasNext() { + return dci.hasNext(); + } + + public Object next() { + final PortalSite psite = (PortalSite) dci.next(); + return new TreeNode() { + public Object getElement() { + return psite; + } + + public Object getKey() { + return psite.getID().toString(); + } + }; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + public TreeNode getRoot(PageState ps) { + if (getRootID() == null) { + return new TreeNode() { + public Object getElement() { + return null; + } + public Object getKey() { + return "root"; + } + }; + } else { + final PortalSite psite = + PortalSite.retrievePortalSite(getRootID()); + return new TreeNode() { + public Object getElement() { + return psite; + } + public Object getKey() { + return psite.getID(); + } + }; + } + } + + public boolean hasChildren(TreeNode n, PageState ps) { + PortalSiteCollection psc; + PortalSite psite = (PortalSite)n.getElement(); + if (psite == null) { + if(m_filterPSites) + psc = PortalSite.getRootPortalSites(); + else + psc = PortalSite.getAllRootPortalSites(); + } else { + if(m_filterPSites) + psc = psite.getChildPortalSites(); + else + psc = psite.getAllChildPortalSites(); + } + boolean isEmpty = psc.isEmpty(); + psc.close(); + return !isEmpty; + } + }; +} + + public static class DefaultRenderer implements TreeCellRenderer { + public Component getComponent(Tree tree, PageState ps, + Object value, boolean isSelected, + boolean isExpanded, boolean isLeaf, + Object key) { + PortalSite psite = (PortalSite)value; + if (psite == null) { return new Label(""); } + String title = psite.getTitle(); + + SimpleContainer result = new SimpleContainer(); + Label l = new Label(title); + if (isSelected) { + l.setFontWeight(Label.BOLD); + result.add(l); + } else { + result.add(new ControlLink(l)); + } + + String psURL = psite.getSiteNode().getURL(); + result.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin."))); + Link viewLink = new Link( new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.view")), psURL); + viewLink.setTargetFrame(Link.NEW_FRAME); + result.add(viewLink); + result.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin."))); + + return result; + } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortletAddForm.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortletAddForm.java new file mode 100644 index 000000000..ca81e4d90 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortletAddForm.java @@ -0,0 +1,869 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + +import com.arsdigita.portalserver.util.GlobalizationUtil; +import com.arsdigita.bebop.BoxPanel; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.CompoundComponent; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormValidationException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.FormInitListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSubmissionListener; +import com.arsdigita.bebop.form.RadioGroup; +import com.arsdigita.bebop.form.Option; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.KernelExcursion; +import com.arsdigita.kernel.Party; +import com.arsdigita.kernel.permissions.PermissionDescriptor; +import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; +import com.arsdigita.kernel.Resource; +import com.arsdigita.kernel.ui.ResourceConfigFormSection; +import com.arsdigita.kernel.ResourceType; +import com.arsdigita.web.Application; +import com.arsdigita.web.ApplicationCollection; +import com.arsdigita.web.ApplicationType; +import com.arsdigita.portalserver.PortalSite; +import com.arsdigita.portalserver.PortalPage; +import com.arsdigita.portalserver.PortalTab; +import com.arsdigita.portal.Portlet; +import com.arsdigita.portal.PortletType; +import com.arsdigita.xml.Element; +import java.math.BigDecimal; +import org.apache.log4j.Logger; + +class PortletAddForm extends CompoundComponent { + private static final Logger s_log = Logger.getLogger(PortletAddForm.class); + + private static final String LEFT_COLUMN = "left"; + private static final String RIGHT_COLUMN = "right"; + + private PortalPage m_portalPage; + + private RequestLocal m_portalsiteRL; + private RequestLocal m_portalIDRL; + + private RequestLocal m_portletTypeRL; + + private RequestLocal m_appTypeRL = new RequestLocal() { + protected Object initialValue(PageState ps) { + PortletType portletType = (PortletType) m_portletTypeRL.get(ps); + if (portletType == null) { return null; } + else { + return portletType.getProviderApplicationType(); + } + } + }; + + private final BigDecimalParameter m_parentAppParam = + new BigDecimalParameter("appID"); + + private RequestLocal m_parentAppRL = new RequestLocal() { + protected Object initialValue(PageState ps) { + BigDecimal id = (BigDecimal) ps.getValue(m_parentAppParam); + if (id == null) { return null; } + return Application.retrieveApplication(id); + } + }; + + private final StringParameter m_columnParam = new StringParameter("colID"); + + private Form m_portletTypeForm; + private Form m_appSelect; + private Form m_newExistingSelect; + private Form m_existingSelect; + private ApplicationCreateComponent m_appCreate; + private ApplicationCreateComponent m_portletCreate; + + public PortletAddForm(RequestLocal portalsiteRL, + RequestLocal portalIDRL, + RequestLocal portletTypeRL) { + super(); + m_portalsiteRL = portalsiteRL; + m_portalIDRL = portalIDRL; + m_portletTypeRL = portletTypeRL; + + final RequestLocal createNewRL = new RequestLocal(); + m_newExistingSelect = buildNewExistingSelect( + m_appTypeRL, m_portalsiteRL, createNewRL,new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + if (createNewRL.get(ps).equals(Boolean.TRUE)) { + m_portalPage.goModal(ps, m_appCreate); + } else { + m_portalPage.goModal(ps, m_appSelect); + } + } + }, + new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + PortletAddForm.this.fireCompletionEvent(ps); + } + }); + add(m_newExistingSelect); + + final RequestLocal makeLocalRL = new RequestLocal(); + m_existingSelect = buildExistingSelect( + m_appTypeRL, m_portalsiteRL, makeLocalRL, new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + if (makeLocalRL.get(ps).equals(Boolean.TRUE)) { + //Assign new portlet to this + PortletType ptype = (PortletType) m_portletTypeRL.get(ps); + PortalSite psite = (PortalSite) m_portalsiteRL.get(ps); + ApplicationCollection apps = + psite.getFullPagePortalSiteApplications(); + ApplicationType appType = (ApplicationType) m_appTypeRL.get(ps); + ApplicationType atp; + Application app = null; + boolean wasFound = false; + while (apps.next()) { + app = apps.getApplication(); + atp = app.getApplicationType(); + if(atp.getID().equals(appType.getID())) + { + apps.close(); + wasFound = true; + break; + } + } + if(wasFound) { + Portlet portlet= Portlet.createPortlet(ptype, app); + addToTab(ps,portlet); + fireCompletionEvent(ps); + } + //throw an exception here for 'else' + } else { + m_portalPage.goModal(ps, m_appSelect); + } + } + }, new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + PortletAddForm.this.fireCompletionEvent(ps); + } + }); + + add(m_existingSelect); + + final RequestLocal selectedAppRL = new RequestLocal(); + m_appSelect = + buildAppSelect(m_appTypeRL, m_portalsiteRL, selectedAppRL, + new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + Application app = (Application) selectedAppRL.get(ps); + if (app == null) { + m_portalPage.goModal(ps, m_appCreate); + } else { + PortletType ptype = (PortletType)m_portletTypeRL.get(ps); + if (m_portletCreate.canCreate(ptype)) { + ps.setValue(m_parentAppParam, app.getID()); + m_portalPage.goModal(ps, m_portletCreate); + } else { + Portlet portlet = Portlet.createPortlet(ptype, app); + addToTab(ps, portlet); + PortletAddForm.this.fireCompletionEvent(ps); + } + } + } + }, new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + m_portalPage.goModal(ps, m_newExistingSelect); + } + }, new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + PortletAddForm.this.fireCompletionEvent(ps); + } + }); + add(m_appSelect); + + // holds the application from app creation + final RequestLocal createdAppRL = new RequestLocal(); + m_appCreate = + buildAppCreate(m_appTypeRL, m_portalsiteRL, createdAppRL, + new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + Application app = (Application) createdAppRL.get(ps); + app.save(); + PortletType ptype = (PortletType) m_portletTypeRL.get(ps); + if (m_portletCreate.canCreate(ptype)) { + ps.setValue(m_parentAppParam, app.getID()); + m_portalPage.goModal(ps, m_portletCreate); + } else { + Portlet portlet = Portlet.createPortlet(ptype, app); + addToTab(ps, portlet); + PortletAddForm.this.fireCompletionEvent(ps); + } + } + }, new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + // XXX: implement back + m_portalPage.goModal(ps, m_newExistingSelect); + } + }, new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + PortletAddForm.this.fireCompletionEvent(ps); + } + } + ); + + add(m_appCreate); + + final RequestLocal portletRL = new RequestLocal(); + + m_portletCreate = buildPortletCreate + (m_portletTypeRL, m_parentAppRL, portletRL, + new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + Portlet portlet = (Portlet) portletRL.get(ps); + addToTab(ps, portlet); + PortletAddForm.this.fireCompletionEvent(ps); + } + }, new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + PortletAddForm.this.fireCompletionEvent(ps); + } + } + ); + + add(m_portletCreate); + } + + protected void fireCompletionEvent(PageState ps) { + ps.reset(this); + m_portalPage.goUnmodal(ps); + super.fireCompletionEvent(ps); + } + + private static final ApplicationCollection getApplicationChoices + (ApplicationType type) { + ApplicationCollection ac = + Application.retrieveAllApplications(); + ac.filterToApplicationType(type.getApplicationObjectType()); + ac.filterToHasFullPageView(); + ac.filterToWorkspaceApplications(); + return ac; + } + + public void activate(PageState ps) { + ApplicationType appType = (ApplicationType) m_appTypeRL.get(ps); + PortalSite psite = (PortalSite) m_portalsiteRL.get(ps); + + if (appType == null) { + PortletType ptype = (PortletType) m_portletTypeRL.get(ps); + + ApplicationType atp = ptype.getProviderApplicationType(); + ApplicationType applicationType; + + if ( atp != null && atp.isSingleton()) { + //1 - get collection of apps for portal + ApplicationCollection apps = psite.getFullPagePortalSiteApplications(); + boolean wasFound = false; + + //2 - iterate through collection and compare with atp + //If in collection, just create and add portlet. + //If not in collection, create app then create portlet + while(apps.next()) { + applicationType = apps.getApplication().getApplicationType(); + if(applicationType.getID().equals(atp.getID())) { + wasFound = true; + Portlet portlet = Portlet.createPortlet(ptype, apps.getApplication()); + addToTab(ps, portlet); + fireCompletionEvent(ps); + break; + } + } + apps.close(); + + if (!wasFound) { + Application newApp = Application.createApplication + (atp, atp.getID().toString(), atp.getTitle(), psite); + Portlet portlet = Portlet.createPortlet(ptype, newApp); + addToTab(ps, portlet); + fireCompletionEvent(ps); + } + } else if (m_portletCreate.canCreate(ptype)) { + ps.setValue(m_parentAppParam, psite.getID()); + m_portalPage.goModal(ps, m_portletCreate); + } else { + Portlet portlet = Portlet.createPortlet(ptype, psite); + addToTab(ps, portlet); + fireCompletionEvent(ps); + } + + return; + } + + //The line below retrieves all app choices in the system + //of type appType. If an app is not a singleton, then + //we can let the if/else code below run. If the app + //*is* a singleton, we need to check if it is + //already installed in this portal site. If so, then + //offer user a choice of existing selections only + //if not, then offer them the typical newExisting select. + if(appType.isSingleton()) + { + if (psite.isAppTypeInPortalSite(appType)) + { + m_portalPage.goModal(ps,m_existingSelect); + } + else + { + m_portalPage.goModal(ps,m_appCreate); + } + } + else + { + ApplicationCollection ac = getApplicationChoices(appType); + if (ac.size() == 0) { + m_portalPage.goModal(ps, m_appCreate); + // XXX: need to handle configuration less applications + // throw new IllegalStateException("can't create"); + } else { + m_portalPage.goModal(ps, m_newExistingSelect); + } + } + } + + public void register(Page p) { + super.register(p); + m_portalPage = (PortalPage) p; + p.addComponentStateParam(this, m_columnParam); + p.addComponentStateParam(this, m_parentAppParam); + } + + private static Form buildNewExistingSelect(final RequestLocal appTypeRL, + final RequestLocal portalsiteRL, + final RequestLocal createNew, + final ActionListener onNext, + final ActionListener onCancel) { + final Form f = new Form("newexist", new BoxPanel(BoxPanel.VERTICAL)) { + public void generateXML(PageState ps, Element parent) { + // force init listeners to run + getFormData(ps); + super.generateXML(ps, parent); + } + }; + + final Label info = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.choose_new_or_existing")); + f.add(info); + + final RadioGroup rg = new RadioGroup("select"); + rg.setLayout(RadioGroup.VERTICAL); + final Label newLabel = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.create_new"), false); + final Label existingLabel = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.pick_existing"), false); + rg.addOption(new Option("create", newLabel)); + rg.addOption(new Option("choose", existingLabel)); + rg.setOptionSelected("create"); + f.add(rg); + + BoxPanel buttons = new BoxPanel(BoxPanel.HORIZONTAL); + final Submit next = new Submit("Next >>"); + final Submit cancel = new Submit("Cancel"); + buttons.add(next); + buttons.add(cancel); + f.add(buttons); + + f.addInitListener(new FormInitListener() { + public void init(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + ApplicationType type = (ApplicationType) appTypeRL.get(ps); + String title = type.getTitle(); + title = title.toLowerCase(); + + info.setLabel("You can choose which " + title + + " to display in the new portlet.", ps); + + newLabel.setLabel("I want to create a new " + title + + " to display in the portlet.", ps); + existingLabel.setLabel( + "I want to choose an existing " + title + + " to display in the portlet.", ps); + } + }); + + f.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + if (cancel.isSelected(ps)) { + onCancel.actionPerformed(new ActionEvent(f, ps)); + return; + } + + String value = (String) rg.getValue(ps); + if ("create".equals(value)) { + createNew.set(ps, Boolean.TRUE); + } else if ("choose".equals(value)) { + createNew.set(ps, Boolean.FALSE); + } else { + throw new IllegalStateException("invalid selection"); + } + onNext.actionPerformed(new ActionEvent(f, ps)); + } + }); + + f.addSubmissionListener(new FormSubmissionListener() { + public void submitted(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + if (cancel.isSelected(ps)) { + onCancel.actionPerformed(new ActionEvent(f, ps)); + return; + } + } + }); + + return f; + } + + private static Form buildExistingSelect(final RequestLocal appTypeRL, + final RequestLocal portalsiteRL, + final RequestLocal makeLocal, + final ActionListener onNext, + final ActionListener onCancel) { + final Form f = new Form("newexist", new BoxPanel(BoxPanel.VERTICAL)) { + public void generateXML(PageState ps, Element parent) { + // force init listeners to run + getFormData(ps); + super.generateXML(ps, parent); + } + }; + + final Label info = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.choose_new_or_existing")); + f.add(info); + + final RadioGroup rg = new RadioGroup("select"); + rg.setLayout(RadioGroup.VERTICAL); + final Label newLabel = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.create_new"), false); + final Label existingLabel = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.pick_existing"), false); + rg.addOption(new Option("local", newLabel)); + rg.addOption(new Option("external", existingLabel)); + rg.setOptionSelected("local"); + f.add(rg); + + BoxPanel buttons = new BoxPanel(BoxPanel.HORIZONTAL); + final Submit next = new Submit("Next >>"); + final Submit cancel = new Submit("Cancel"); + buttons.add(next); + buttons.add(cancel); + f.add(buttons); + + f.addInitListener(new FormInitListener() { + public void init(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + ApplicationType type = (ApplicationType) appTypeRL.get(ps); + String title = type.getTitle(); + title = title.toLowerCase(); + + info.setLabel("You can choose which " + title + + " to display in the new portlet.", ps); + + newLabel.setLabel("I want to display the "+ title + + " for this portal in the portlet.", ps); + existingLabel.setLabel( + "I want to choose a " + title + + " from another portal to display in the portlet.", ps); + } + }); + + f.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + if (cancel.isSelected(ps)) { + onCancel.actionPerformed(new ActionEvent(f, ps)); + return; + } + + String value = (String) rg.getValue(ps); + if ("local".equals(value)) { + makeLocal.set(ps, Boolean.TRUE); + } else if ("external".equals(value)) { + makeLocal.set(ps, Boolean.FALSE); + } else { + throw new IllegalStateException("invalid selection"); + } + onNext.actionPerformed(new ActionEvent(f, ps)); + } + }); + + f.addSubmissionListener(new FormSubmissionListener() { + public void submitted(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + if (cancel.isSelected(ps)) { + onCancel.actionPerformed(new ActionEvent(f, ps)); + return; + } + } + }); + + return f; + } + + private static Form buildAppSelect(final RequestLocal appType, + final RequestLocal portalsiteRL, + final RequestLocal selectedApp, + final ActionListener onNext, + final ActionListener onBack, + final ActionListener onCancel) { + final Form f = new Form("appselect", new BoxPanel(BoxPanel.VERTICAL)) { + public void generateXML(PageState ps, Element parent) { + // force init listeners to run + getFormData(ps); + super.generateXML(ps, parent); + } + }; + + SimpleContainer header = new SimpleContainer(); + Label header1 = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.you_have_opted_to_display_an_existing")); + final Label header2 = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.apptype")); + Label header3 = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.in_the_new_portlet")); + header.add(header1); + header.add(header2); + header.add(header3); + f.add(header); + + SimpleContainer choose = new SimpleContainer(); + Label choose1 = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.choose_one_of_the")); + final Label choose2 = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.apptype")); + Label choose3 = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.already_in_this_workspace")); + choose.add(choose1); + choose.add(choose2); + choose.add(choose3); + f.add(choose); + + final RadioGroup rg = new RadioGroup("appselect"); + rg.setLayout(RadioGroup.VERTICAL); + f.add(rg); + + BoxPanel buttons = new BoxPanel(BoxPanel.HORIZONTAL); + final Submit next = new Submit("Next >>"); + buttons.add(next); + final Submit back = new Submit("Back <<"); + buttons.add(back); + final Submit cancel = new Submit("Cancel"); + buttons.add(cancel); + f.add(buttons); + + f.addInitListener(new FormInitListener() { + public void init(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + + ApplicationType type = (ApplicationType) appType.get(ps); + + String title = type.getTitle(); + title = title.toLowerCase(); + + header2.setLabel(title, ps); + // XXX: need plural + choose2.setLabel(title, ps); + + ApplicationCollection ac = getApplicationChoices(type); + ac.orderByParentTitle(); + ac.orderByTitle(); + while (ac.next()) { + Label l = new Label(ac.getTitle() + " ( " + + ac.getParentTitle() + " ) "); + l.setFontWeight(Label.BOLD); + rg.addOption(new Option(ac.getID().toString(), l), ps); + } + } + }); + + f.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + String idStr = (String) rg.getValue(ps); + if (cancel.isSelected(ps)) { + onCancel.actionPerformed(new ActionEvent(f, ps)); + return; + } else if (back.isSelected(ps)) { + onBack.actionPerformed(new ActionEvent(f, ps)); + return; + } + + BigDecimal id; + try { + id = new BigDecimal(idStr); + selectedApp.set( + ps, Application.retrieveApplication(id)); + onNext.actionPerformed(new ActionEvent(f, ps)); + } catch (NumberFormatException nfe) { + throw new IllegalStateException("bad id"); + } + } + }); + + f.addSubmissionListener(new FormSubmissionListener() { + public void submitted(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + if (cancel.isSelected(ps)) { + onCancel.actionPerformed(new ActionEvent(f, ps)); + return; + } + } + }); + + return f; + } + + private static ApplicationCreateComponent buildAppCreate + (final RequestLocal appTypeRL, final RequestLocal portalsiteRL, + final RequestLocal createdAppRL, final ActionListener onNext, + final ActionListener onBack, final ActionListener onCancel) { + + return new ApplicationCreateComponent + (appTypeRL, portalsiteRL, false, + new ApplicationCreateComponent.Builder() { + public Component build + (final ResourceConfigFormSection acfs) { + final Form f = new Form + ("appcreate", new BoxPanel(BoxPanel.VERTICAL)) { + public void generateXML + (PageState ps, Element parent) { + // force init listeners to run + getFormData(ps); + super.generateXML(ps, parent); + } + }; + + SimpleContainer header = new SimpleContainer(); + Label header1 = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.you_chose_to_create_a_new")); + final Label header2 = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.apptype")); + Label header3 = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.in_the_new_portlet")); + header.add(header1); + header.add(header2); + header.add(header3); + f.add(header); + + f.add(acfs); + + BoxPanel buttons = new BoxPanel(BoxPanel.HORIZONTAL); + final Submit next = new Submit("Next >>"); + buttons.add(next); + final Submit back = new Submit("Back <<"); + buttons.add(back); + final Submit cancel = new Submit("Cancel"); + buttons.add(cancel); + f.add(buttons); + + f.addInitListener(new FormInitListener() { + public void init(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + ApplicationType type = (ApplicationType) + appTypeRL.get(ps); + String title = type.getTitle(); + title = title.toLowerCase(); + header2.setLabel(title, ps); + } + }); + + f.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) + throws FormValidationException { + PageState ps = ev.getPageState(); + + if (next.isSelected(ps)) { + + + if (s_log.isDebugEnabled()) { + s_log.debug + ("Using application config " + + "form section " + acfs + + " to create an application"); + } + + final Application app =(Application) acfs.createResource(ps); + createdAppRL.set(ps, app); + onNext.actionPerformed(new ActionEvent(f, ps)); + grantWrite(app); + } else if (back.isSelected(ps)) { + onBack.actionPerformed(new ActionEvent(f, ps)); + } else if (cancel.isSelected(ps)) { + onCancel.actionPerformed(new ActionEvent(f, ps)); + } + } + }); + + f.addSubmissionListener(new FormSubmissionListener() { + public void submitted(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + if (cancel.isSelected(ps)) { + onCancel.actionPerformed(new ActionEvent(f, ps)); + return; + } + } + }); + return f; + } + }); + } + + private static ApplicationCreateComponent buildPortletCreate + (final RequestLocal portletTypeRL, final RequestLocal parentAppRL, + final RequestLocal portletRL, final ActionListener onNext, + final ActionListener onCancel) { + return new ApplicationCreateComponent + (portletTypeRL, parentAppRL, true, + new ApplicationCreateComponent.Builder() { + public Component build + (final ResourceConfigFormSection acfs) { + final Form f = new Form + ("portcreat", new BoxPanel(BoxPanel.VERTICAL)) { + public void generateXML(PageState ps, Element p) { + // force init listeners to run + getFormData(ps); + super.generateXML(ps, p); + } + }; + + SimpleContainer header = new SimpleContainer(); + Label header1 = new Label + ("Choose display options for the new "); + final Label header2 = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.apptype")); + final Label header2a = new Label(" "); //sep char + Label header3 = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.portlet")); + header.add(header1); + header.add(header2); + header.add(header2a); + header.add(header3); + f.add(header); + + f.add(acfs); + + BoxPanel buttons = new BoxPanel(BoxPanel.HORIZONTAL); + final Submit next = new Submit("Next >>"); + buttons.add(next); + final Submit cancel = new Submit("Cancel"); + buttons.add(cancel); + f.add(buttons); + + f.addInitListener(new FormInitListener() { + public void init(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + ResourceType type = (ResourceType) + portletTypeRL.get(ps); + String title = type.getTitle(); + title = title.toLowerCase(); + header2.setLabel(title, ps); + } + }); + + f.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + + if (s_log.isDebugEnabled()) { + s_log.debug("Using application config " + + "form section " + acfs + + " to create a new portlet"); + } + + if (next.isSelected(ps)) { + Resource app = (Resource) acfs.createResource(ps); + + portletRL.set(ps, app); + + onNext.actionPerformed(new ActionEvent(f, ps)); + + grantWrite(app); + } else if (cancel.isSelected(ps)) { + onCancel.actionPerformed + (new ActionEvent(f, ps)); + } + } + }); + + f.addSubmissionListener(new FormSubmissionListener() { + public void submitted(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + if (cancel.isSelected(ps)) { + onCancel.actionPerformed(new ActionEvent(f, ps)); + return; + } + } + }); + + return f; + } + }); + } + + private void addToTab(PageState ps, Portlet newPortlet) { + BigDecimal ptabID = (BigDecimal)m_portalIDRL.get(ps); + PortalTab ptab = PortalTab.retrieveTab(ptabID); + + String column = (String)ps.getValue(m_columnParam); + if (column == null) { + if (newPortlet.getProfile().equals(PortletType.WIDE_PROFILE)) { + ptab.addPortlet(newPortlet, 2); + } else { + ptab.addPortlet(newPortlet, 1); + } + } else { + if (LEFT_COLUMN.equals(ps.getValue(m_columnParam))) { + ptab.addPortlet(newPortlet, 1); + } else { + ptab.addPortlet(newPortlet, 2); + } + } + ptab.save(); + newPortlet.save(); + } + + private static final void grantWrite(final Resource app) { + final Party current = Kernel.getContext().getParty(); + + if (current == null || current.equals(Kernel.getSystemParty())) { + return; + } + + new KernelExcursion() { + public void excurse() { + setParty(Kernel.getSystemParty()); + + app.save(); + + PermissionService.grantPermission + (new PermissionDescriptor + (PrivilegeDescriptor.WRITE, app, current)); + } + }.run(); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortletLayoutComponent.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortletLayoutComponent.java new file mode 100644 index 000000000..5d733cbc4 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/PortletLayoutComponent.java @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import java.io.IOException; + +import java.math.BigDecimal; + + +import com.arsdigita.portalserver.PortalTab; +import com.arsdigita.portalserver.PortalSite; + +import com.arsdigita.portal.Portal; +import com.arsdigita.portal.Portlet; +import com.arsdigita.portal.PortletCollection; +import com.arsdigita.portal.AgentPortlet; + + +import com.arsdigita.xml.Element; + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.SimpleComponent; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.util.BebopConstants; + + + +/** + *

    This component provides UI for modifying the layout of a single + * portal and for adding new portlets to it.

    + **/ +abstract class PortletLayoutComponent + extends SimpleComponent + implements BebopConstants { + + private static final String PREV_EVENT = "prev"; + private static final String NEXT_EVENT = "next"; + private static final String LEFT_EVENT = "left"; + private static final String RIGHT_EVENT = "right"; + private static final String DEL_EVENT = "del"; + private static final String CONFIG_EVENT = "cfg"; + + private static final String PORTAL_XML_NS = + "http://www.arsdigita.com/portalserver/1.0"; + + + private final RequestLocal m_portalsiteRL; + private final RequestLocal m_portalIDRL; + + + public PortletLayoutComponent(RequestLocal portalsiteRL, + RequestLocal portalIDRL) { + + m_portalsiteRL = portalsiteRL; + m_portalIDRL = portalIDRL; + + } + + + // Generate XML for the given portlet + private void generateXMLHelper(PageState ps, + Portlet portlet, + Element portalElt, + boolean hasPrev, + boolean hasNext, + int numCols, + String layout) { + + //These boolean values are used to prevent movement + //of portlets into, out of, or within locked cell regions + boolean isLocked = false; + boolean canMoveLeft = true; + boolean canMoveRight = true; + + Element portletElt = + portalElt.newChildElement(BEBOP_PORTLET, + Component.BEBOP_XML_NS); + + // Standard portlet attributes + portletElt.addAttribute("title", portlet.getTitle()); + portletElt.addAttribute("cellNumber", + Integer.toString(portlet.getCellNumber())); + portletElt.addAttribute("sortKey", + Integer.toString(portlet.getSortKey())); + portletElt.addAttribute("profile", portlet.getProfile()); + portletElt.addAttribute("configure", "true"); + + String portletIDstr = portlet.getID().toString(); + + // Add attributes containing URLs that fire control events + // for various portlet actions + try { + + int cellNum = portlet.getCellNumber(); + if(layout.charAt(cellNum - 1) == 'n' || + layout.charAt(cellNum - 1) == 'w') + isLocked = true; + + if(layout.length() == 2) { + if(cellNum == 1) { + if(layout.charAt(1) == 'n' || + layout.charAt(1) == 'w') { + canMoveRight = false; + } + } + if(cellNum == 2) { + if(layout.charAt(0) == 'n' || + layout.charAt(0) == 'w') { + canMoveLeft = false; + } + } + } + + if(layout.length() == 3) { + if(cellNum == 1) { + if(layout.charAt(1) == 'n' || + layout.charAt(1) == 'w') { + canMoveRight = false; + } + } + if(cellNum == 3) { + if(layout.charAt(1) == 'n' || + layout.charAt(1) == 'w') { + canMoveLeft = false; + } + } + if(cellNum == 2) { + if(layout.charAt(0) == 'n' || + layout.charAt(0) == 'w') { + canMoveLeft = false; + } + if(layout.charAt(2) == 'n' || + layout.charAt(2) == 'w') { + canMoveRight = false; + } + } + + } + + + // Add attribute containing URL for "delete" link + // unless this portlet is in a locked cell. + if(!isLocked) { + ps.setControlEvent(PortletLayoutComponent.this, + DEL_EVENT, portletIDstr); + portletElt.addAttribute("delURL", ps.stateAsURL()); + } + + // Add attribute containing URL for "config" link + // unless the portlet is an agent portlet for + // another superportal portlet. + if(! (portlet instanceof AgentPortlet)) { + ps.setControlEvent(PortletLayoutComponent.this, + CONFIG_EVENT, portletIDstr); + portletElt.addAttribute("cfgURL", ps.stateAsURL()); + } + + // Maybe add attribute containing URL for "move up" link + if(!isLocked) { + if (hasPrev) { + ps.setControlEvent(PortletLayoutComponent.this, + PREV_EVENT, portletIDstr); + portletElt.addAttribute("prevURL", ps.stateAsURL()); + } + } + + // Maybe add attribute containing URL for "move down" link + if(!isLocked) { + if (hasNext) { + ps.setControlEvent(PortletLayoutComponent.this, + NEXT_EVENT, portletIDstr); + portletElt.addAttribute("nextURL", ps.stateAsURL()); + } + } + + //When to draw move left arrow: + //1 column...never + //2 columns...when cell num == 2 + //3 columns...when cell num > 1 + if((!isLocked) && (canMoveLeft)) { + if (numCols != 1 && + ((numCols == 2 && cellNum == 2) || + (numCols == 3 && cellNum > 1))) { + ps.setControlEvent(PortletLayoutComponent.this, + LEFT_EVENT, portletIDstr); + portletElt.addAttribute("leftURL", ps.stateAsURL()); + } + } + + //When to draw move right arrow + //1 column...never + //2 columns...when cell num != 2 + //3 columns...when cell num < numColumns + if((!isLocked) && (canMoveRight)) { + if (numCols != 1 && + ((numCols == 2 && cellNum != 2) || + (numCols == 3 && cellNum < numCols))) { + ps.setControlEvent(PortletLayoutComponent.this, + RIGHT_EVENT, portletIDstr); + portletElt.addAttribute("rightURL", ps.stateAsURL()); + } + } + + ps.clearControlEvent(); + + } catch (IOException ex) { + throw new IllegalStateException("Caught IOException: " + + ex.getMessage()); + } + + // Put in the "guts" of the portlet - a description taken from + // the portlet type. + Element labelElt = + portletElt.newChildElement("bebop:label", + Component.BEBOP_XML_NS); + String desc = portlet.getPortletType().getDescription(); + if (desc == null) { + desc = ""; + } + labelElt.setText(desc); + } + + + /** + *

    Generate the XML for the configurable portal display. Much + * of the code for this is cribbed from {@link + * com.arsdigita.bebop.Portal com.arsdigita.bebop.Portal's} + * generateXML.

    + **/ + public void generateXML(PageState ps, Element parentElt) { + + BigDecimal portalID = (BigDecimal)m_portalIDRL.get(ps); + if (portalID == null) { + return; + } + + if (!(PortalTab.doesTabExist(portalID))) { + return; + } + + int numCols = 0; + + PortalTab ptab = PortalTab.retrieveTab(portalID); + String layout = ptab.getLayout(); + //Layout is W for 1 column, WN or NW for 2 cols, or NWN or NNN 3 cols.. + if(layout == null) + numCols = 2; + else + numCols = layout.length(); + + Element portalElt = + parentElt.newChildElement(BEBOP_PORTAL, Component.BEBOP_XML_NS); + + exportAttributes(portalElt); + + portalElt.addAttribute("title", ptab.getTitle()); + portalElt.addAttribute("configure", "true"); + + //If tab has locked cell regions, these are represented by + //lower case style chars...we need to upper case them before + //using them as a portaltab attr. + String layoutstyle = ptab.getLayout(); + if(layoutstyle != null) + layoutstyle = layoutstyle.toUpperCase(); + portalElt.addAttribute("style", layoutstyle); + + PortletCollection portletCollection = ptab.getPortlets(); + + if (!portletCollection.next()) { + return; + } + + // Loop through portlets, generating XML for each + boolean hasPrev = false; + Portlet curr = portletCollection.getPortlet(); + Portlet next = null; + while (portletCollection.next()) { + next = portletCollection.getPortlet(); + // If the next portlet is not in the same cell as the + // current portlet, then the current portlet will have no + // "move down" link, and the next portlet will have + // no "move up" link. + if (curr.getCellNumber() != next.getCellNumber()) { + generateXMLHelper(ps, curr, portalElt, hasPrev, false, numCols, + layout); + hasPrev = false; + } else { + generateXMLHelper(ps, curr, portalElt, hasPrev, true, numCols, + layout); + hasPrev = true; + } + curr = next; + } + + // Generate XML for the last portlet + generateXMLHelper(ps, curr, portalElt, hasPrev, false, numCols, layout); + } + + + public void respond(PageState ps) { + String event = ps.getControlEventName(); + + if (CONFIG_EVENT.equals(event)) { + BigDecimal portletID = new BigDecimal(ps.getControlEventValue()); + handleConfigure(ps, portletID); + return; + } + + BigDecimal portletID = new BigDecimal(ps.getControlEventValue()); + Portlet portlet = Portlet.retrievePortlet(portletID); + Portal portal = portlet.getPortal(); + + if (NEXT_EVENT.equals(event)) { + portal.swapPortletWithNext(portlet); + } else if (PREV_EVENT.equals(event)) { + portal.swapPortletWithPrevious(portlet); + } else if (LEFT_EVENT.equals(event)) { + int cell = portlet.getCellNumber(); + cell = cell - 1; + if (cell < 1) { cell = 1; } + portlet.setCellNumber(cell); + portlet.save(); + } else if (RIGHT_EVENT.equals(event)) { + int cello = portlet.getCellNumber(); + cello = cello + 1; + if (cello > 3) { cello = 3; } + portlet.setCellNumber(cello); + portlet.save(); + } else if (DEL_EVENT.equals(event)) { + portlet.delete(); + } else { + throw new IllegalStateException("Unknown portlet layout event"); + } + + // Portal should make sure a moved portlet gets saved, so + // saving the portlet is unnecessary. + //portlet.save(); + portal.save(); + } + + + abstract protected void handleConfigure(PageState ps, BigDecimal portletID); +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/RelatedPortalsPane.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/RelatedPortalsPane.java new file mode 100644 index 000000000..e090c6da2 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/RelatedPortalsPane.java @@ -0,0 +1,344 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.BoxPanel; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.Container; +import com.arsdigita.bebop.DynamicListWizard; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.List; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.PropertySheet; +import com.arsdigita.bebop.PropertySheetModel; +import com.arsdigita.bebop.PropertySheetModelBuilder; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.Tree; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.ChangeEvent; +import com.arsdigita.bebop.event.ChangeListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.PrintEvent; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.bebop.list.ListModel; +import com.arsdigita.bebop.list.ListModelBuilder; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.bebop.tree.TreeModel; +import com.arsdigita.kernel.ui.ACSObjectSelectionModel; +import com.arsdigita.portalserver.PortalSite; +import com.arsdigita.portalserver.PortalSiteCollection; +import com.arsdigita.xml.Element; +import org.apache.log4j.Logger; +import com.arsdigita.globalization.GlobalizedMessage; + + +public class RelatedPortalsPane { + + private static final Logger s_log = Logger.getLogger(RelatedPortalsPane.class); + + private RelatedPortalsPane() { } // no construction allowed + + public static Component create(final RequestLocal portalsiteRL) { + // related portals + final ACSObjectSelectionModel relatedSelection = + new ACSObjectSelectionModel("relatedws"); + + List rList = new List(new ListModelBuilder() { + public void lock() { } + public boolean isLocked() { return true; } + public ListModel makeModel(List l, PageState ps) { + return new RelatedPortalsModel((PortalSite)portalsiteRL.get(ps)); + } + }); + rList.setSelectionModel(relatedSelection); + Label noRelated = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.no_linked_workspaces")); + noRelated.setFontWeight(Label.ITALIC); + rList.setEmptyView(noRelated); + + final DynamicListWizard related = + new DynamicListWizard("Linked Portals", rList, relatedSelection, + "Link to a portal", new Label("")); + + related.setAddPane(relatedAddPane(portalsiteRL, new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState ps = e.getPageState(); + related.reset(ps); + } + })); + + related.setEditPane(relatedEditPane(portalsiteRL, new RequestLocal() { + protected Object initialValue(PageState ps) { + return relatedSelection.getSelectedObject(ps); + } + }, new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState ps = e.getPageState(); + related.reset(ps); + } + })); + + + // childportals + final ACSObjectSelectionModel childSelection = + new ACSObjectSelectionModel("childws"); + + List cList = new List(new ListModelBuilder() { + public void lock() { } + public boolean isLocked() { return true; } + public ListModel makeModel(List l, PageState ps) { + return new ChildPortalsModel( (PortalSite) portalsiteRL.get(ps)); + } + }); + cList.setSelectionModel(childSelection); + Label noChildren = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.no_child_workspaces")); + noChildren.setFontWeight(Label.ITALIC); + cList.setEmptyView(noChildren); + + final DynamicListWizard child = + new DynamicListWizard("Child Portals", cList, childSelection, + "Add a child portal", new Label("")); + + final RequestLocal newChildPortal = new RequestLocal(); + child.setAddPane( ChildPortalCreateForm.create(portalsiteRL, + newChildPortal, new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState ps = e.getPageState(); + childSelection.setSelectedKey(ps,((PortalSite) newChildPortal.get(ps)).getID() .toString()); + } + })); + + child.setEditPane(childEditPane(portalsiteRL, new RequestLocal() { + protected Object initialValue(PageState ps) { + return childSelection.getSelectedObject(ps); + } + })); + + Container retval = new SimpleContainer(); + retval.add(related); + retval.add(child); + + return retval; + } + + private static Component childEditPane(final RequestLocal portalsiteRL, + final RequestLocal childPortal) { + final Container retval = new BoxPanel(BoxPanel.VERTICAL); + + Label header = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.child_workspace_info")); + header.setFontWeight(Label.BOLD); + retval.add(header); + + retval.add(new PropertySheet(new PropertySheetModelBuilder() { + public void lock() { } + public boolean isLocked() { return true; } + public PropertySheetModel makeModel(PropertySheet sheet, + final PageState ps) { + return new PortalModel((PortalSite) childPortal.get(ps)); + } + })); + + BoxPanel bp = new BoxPanel(BoxPanel.HORIZONTAL); + bp.add(new Link( new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.go_to_this_workspace")), new PrintListener() { + public void prepare(PrintEvent e) { + PageState ps = e.getPageState(); + Link target = (Link) e.getTarget(); + PortalSite cp = (PortalSite) childPortal.get(ps); + target.setTarget(cp.getPrimaryURL()); + } + })); + bp.add(new Link( new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.administer_this_workspace")), new PrintListener() { + public void prepare(PrintEvent e) { + PageState ps = e.getPageState(); + Link target = (Link) e.getTarget(); + PortalSite cp = (PortalSite) childPortal.get(ps); + target.setTarget(cp.getPrimaryURL() + "admin"); + } + })); + + retval.add(bp); + + return retval; + } + + private static Component relatedAddPane(final RequestLocal portalsiteRL, + final ActionListener onAdd) { + final Form confirmation = new Form("confirm", new SimpleContainer()); + confirmation.setMethod(Form.POST); + final Container retval = new BoxPanel(BoxPanel.VERTICAL) { + public void register(Page p) { + p.setVisibleDefault(confirmation, false); + } + }; + + final Tree psTree = new Tree(new PortalTreeModelBuilder()) { + public void generateXML(PageState ps, Element parent) { + TreeModel tm = getTreeModel(ps); + String key = (String) tm.getRoot(ps).getKey(); + expand((String) tm.getRoot(ps).getKey(), ps); + super.generateXML(ps, parent); + } + }; + psTree.setCellRenderer( new PortalTreeModelBuilder.DefaultRenderer()); + final ACSObjectSelectionModel treeSelection = + new ACSObjectSelectionModel("wstreeselect"); + psTree.setSelectionModel(treeSelection); + + retval.add(psTree); + + treeSelection.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + PageState ps = e.getPageState(); + confirmation.setVisible(ps, true); + } + }); + + confirmation.add(new Submit("Link selected portal")); + confirmation.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent e) { + PageState ps = e.getPageState(); + PortalSite related = + (PortalSite) treeSelection.getSelectedObject(ps); + + PortalSite psite = (PortalSite) portalsiteRL.get(ps); + PortalSiteCollection current = psite.getRelatedPortalSites(); + current.filterToPortalSite(related.getID()); + if (current.size() == 0) { + psite.addRelatedPortalSite(related); + psite.save(); + } + + ps.reset(retval); + onAdd.actionPerformed(new ActionEvent(retval, ps)); + } + }); + + retval.add(confirmation); + + return retval; + } + + private static Component relatedEditPane( final RequestLocal portalsiteRL, + final RequestLocal relatedPortal, final ActionListener onRemove) { + + final Container retval = new BoxPanel(BoxPanel.VERTICAL); + + Label header = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.linked_workspace_info")); + header.setFontWeight(Label.BOLD); + retval.add(header); + + retval.add(new PropertySheet(new PropertySheetModelBuilder() { + public void lock() { } + public boolean isLocked() { return true; } + public PropertySheetModel makeModel(PropertySheet sheet, + final PageState ps) { + return new PortalModel( + (PortalSite) relatedPortal.get(ps)); + } + })); + + final ActionLink unLinkPortalPrompt = new ActionLink( + "Remove link to portal?"); + unLinkPortalPrompt.setConfirmation("Really remove link to portal?"); + unLinkPortalPrompt.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState ps = e.getPageState(); + PortalSite psite = (PortalSite) portalsiteRL.get(ps); + psite.removeRelatedPortalSite((PortalSite) relatedPortal.get(ps)); + psite.save(); + onRemove.actionPerformed(new ActionEvent(retval, ps)); + } + }); + retval.add(unLinkPortalPrompt); + + return retval; + } + + static class PortalModel implements PropertySheetModel { + private PortalSite m_p; + private int m_counter = -1; + + PortalModel(PortalSite p) { m_p = p; } + + public boolean nextRow() { + if (m_counter == 1) { return false; } + else { m_counter++; return true; } + } + + /** + * @deprecated use getGlobalizedLabel instead + */ + public String getLabel() { + return getGlobalizedLabel().getKey(); + } + + public GlobalizedMessage getGlobalizedLabel() { + if (m_counter == 0) { + return GlobalizationUtil.globalize("cw.workspace.ui.admin.title"); + } else if (m_counter == 1) { + return GlobalizationUtil.globalize("cw.workspace.ui.admin.mission"); + } else { + throw new IllegalStateException("invalid counter"); + } + } + + public String getValue() { + if (m_counter == 0) { + return m_p.getTitle(); + } else if (m_counter == 1) { + return m_p.getMission(); + } else if (m_counter == 2) { + PortalSite parent = PortalSite.getPortalSiteForApplication(m_p); + if (parent == null) { return "None"; } + return parent.getTitle(); + } else { + throw new IllegalStateException("invalid counter"); + } + } + } + + private static class ChildPortalsModel implements ListModel { + private PortalSiteCollection m_psc; + public ChildPortalsModel(PortalSite p) { + m_psc = p.getChildPortalSites(); + } + public boolean next() { return m_psc.next(); } + public String getKey() { return m_psc.getID().toString(); } + public Object getElement() { return m_psc.getDisplayName(); } + } + + private static class RelatedPortalsModel implements ListModel { + private PortalSiteCollection m_psc; + public RelatedPortalsModel(PortalSite p) { + m_psc = p.getRelatedPortalSites(); + } + public boolean next() { return m_psc.next(); } + public String getKey() { return m_psc.getID().toString(); } + public Object getElement() { return m_psc.getDisplayName(); } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/RolePane.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/RolePane.java new file mode 100644 index 000000000..77839d240 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/RolePane.java @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.portalserver.permissions.PartyPermissionEdit; + +import com.arsdigita.kernel.ui.ACSObjectSelectionModel; +import com.arsdigita.toolbox.ui.ACSObjectCollectionListModel; + +import com.arsdigita.kernel.permissions.*; +import com.arsdigita.portalserver.*; +import com.arsdigita.bebop.*; +import com.arsdigita.bebop.list.*; +import com.arsdigita.bebop.form.*; +import com.arsdigita.bebop.event.*; +import com.arsdigita.bebop.parameters.*; + +import com.arsdigita.bebop.list.ListModelBuilder; +import com.arsdigita.bebop.list.ListModel; + +public class RolePane { + + public static Component create(final RequestLocal portalsiteRL) { + final ACSObjectSelectionModel selectionModel = + new ACSObjectSelectionModel("selectedRole"); + + List rList = new List(new ListModelBuilder() { + public ListModel makeModel(List l, PageState ps) { + PortalSite p = (PortalSite)portalsiteRL.get(ps); + return new ACSObjectCollectionListModel(p.getRoles()) { + public Object getElement() { + RoleCollection rc = (RoleCollection)getCollection(); + if (rc.isSystem()) { + return rc.getRoleName() + "*"; + } else { + return rc.getRoleName(); + } + } + }; + } + public void lock() {} + public boolean isLocked() { return true; } + }); + rList.setSelectionModel(selectionModel); + Label emptyView = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.no_roles_defined")); + emptyView.setFontWeight(Label.ITALIC); + rList.setEmptyView(emptyView); + + final DynamicListWizard dlw = + new DynamicListWizard("Roles", rList, selectionModel, "Add a role", new Label("")); + + final RequestLocal roleRL = new RequestLocal() { + public Object initialValue(PageState ps) { + return (Role)selectionModel.getSelectedObject(ps); + } + }; + + dlw.setAddPane(addPane(roleRL, portalsiteRL, new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + selectionModel.setSelectedObject(ps, (Role)roleRL.get(ps)); + } + })); + + dlw.setEditPane(editPane(roleRL, portalsiteRL, new ActionListener() { + public void actionPerformed(ActionEvent ev) { + PageState ps = ev.getPageState(); + selectionModel.setSelectedObject(ps, null); + } + })); + + return dlw; + } + + + private static Component addPane(final RequestLocal roleRL, + final RequestLocal portalsiteRL, + final ActionListener onAdd) { + final Form result = new Form("roleAdd"); + + result.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.role_name"))); + + final TextField roleNameField = new TextField("roleName"); + roleNameField + .getParameterModel() + .addParameterListener(new NotEmptyValidationListener()); + + result.add(roleNameField); + + result.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.assignee_title"))); + + final TextField assigneeTitleField = new TextField("assigneeTitle"); + assigneeTitleField + .getParameterModel() + .addParameterListener(new NotEmptyValidationListener()); + + result.add(assigneeTitleField); + + result.add(new Label()); + result.add(new Submit("Add Role")); + + result.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + String roleName = (String)roleNameField.getValue(ps); + String assigneeTitle = (String)assigneeTitleField.getValue(ps); + // XXX: creating roles with no descriptions + PortalSite psite = (PortalSite)portalsiteRL.get(ps); + Role newRole = + Role.createRole((PortalSite)portalsiteRL.get(ps), + roleName, assigneeTitle, ""); + newRole.save(); + PermissionService.grantPermission( + new PermissionDescriptor(PrivilegeDescriptor.READ,psite,newRole)); + roleRL.set(ps, newRole); + onAdd.actionPerformed(new ActionEvent(result, ps)); + } + }); + + return result; + } + + + + private static Component editPane(final RequestLocal roleRL, + final RequestLocal portalsiteRL, + final ActionListener onDelete) { + + final BoxPanel result = new BoxPanel(); + result.setWidth("100%"); + + GridPanel formPanel = new GridPanel(2); + // formPanel.setWidth("100%"); + final Form properties = new Form("roleEdit", formPanel); + + properties.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.role_name"))); + + final TextField roleNameEntry = new TextField("roleName") { + public boolean isVisible(PageState ps) { + Role r = (Role)roleRL.get(ps); + return ((r != null) && !r.isSystem()); + } + }; + roleNameEntry.addValidationListener(new NotEmptyValidationListener()); + + final Label roleNameDisplay = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.null_role")) { + public boolean isVisible(PageState ps) { + Role r = (Role)roleRL.get(ps); + return !roleNameEntry.isVisible(ps); + } + }; + roleNameDisplay.addPrintListener(new PrintListener() { + public void prepare(PrintEvent ev) { + Role r = (Role)roleRL.get(ev.getPageState()); + if (r == null) { + return; + } + Label tgt = (Label)ev.getTarget(); + tgt.setLabel(r.getRoleName()); + } + }); + + + final SimpleContainer roleNameComposite = new SimpleContainer(); + roleNameComposite.add(roleNameEntry); + roleNameComposite.add(roleNameDisplay); + properties.add(roleNameComposite); + + properties.add(new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.assignee_title"))); + + final TextField titleEntry = new TextField("assigneeTitle") { + public boolean isVisible(PageState ps) { + return roleNameEntry.isVisible(ps); + } + }; + titleEntry.addValidationListener( new NotEmptyValidationListener()); + + final Label titleDisplay = new Label(GlobalizationUtil.globalize("cw.workspace.ui.admin.null_assignee_title")) { + public boolean isVisible(PageState ps) { + return roleNameDisplay.isVisible(ps); + } + }; + titleDisplay.addPrintListener(new PrintListener() { + public void prepare(PrintEvent ev) { + Role r = (Role)roleRL.get(ev.getPageState()); + if (r == null) { + return; + } + Label tgt = (Label)ev.getTarget(); + tgt.setLabel(r.getAssigneeTitle()); + } + }); + + final SimpleContainer titleComposite = new SimpleContainer(); + titleComposite.add(titleEntry); + titleComposite.add(titleDisplay); + properties.add(titleComposite); + + + properties.add(new Label()); + properties.add(new Submit("Update Role") { + public boolean isVisible(PageState ps) { + return roleNameEntry.isVisible(ps); + } + }); + + properties.addInitListener(new FormInitListener() { + public void init(FormSectionEvent ev) { + PageState ps = ev.getPageState(); + Role role = (Role)roleRL.get(ps); + roleNameEntry.setValue(ps, role.getRoleName()); + } + }); + + properties.addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) + throws FormProcessException { + PageState ps = ev.getPageState(); + Role role = (Role)roleRL.get(ps); + if (!role.isSystem()) { + String newRoleName = (String)roleNameEntry.getValue(ps); + String newTitle = (String)titleEntry.getValue(ps); + role.setRoleName(newRoleName); + role.setAssigneeTitle(newTitle); + role.save(); + } + } + }); + result.add(properties); + + final ActionLink deleteRole = new ActionLink( (String) GlobalizationUtil.globalize("cw.workspace.ui.admin.delete_role").localize()) { + public boolean isVisible(PageState ps) { + Role r = (Role)roleRL.get(ps); + return !r.isSystem(); + } + }; + deleteRole.setConfirmation( + "Really delete portal role?"); + deleteRole.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState ps = e.getPageState(); + Role r = (Role)roleRL.get(ps); + r.delete(); + onDelete.actionPerformed(new ActionEvent(result, ps)); + } + }); + result.add(deleteRole); + + + final PartyPermissionEdit permWidget = + new PartyPermissionEdit("Privileges", portalsiteRL, roleRL); + result.add(permWidget); + + return result; + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/ThemesPane.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/ThemesPane.java new file mode 100644 index 000000000..a6a936604 --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/ThemesPane.java @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + + +import com.arsdigita.portalserver.util.GlobalizationUtil; + +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.BoxPanel; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.SimpleComponent; +import com.arsdigita.bebop.Container; +import com.arsdigita.bebop.DynamicListWizard; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormSection; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.ModalContainer; +import com.arsdigita.bebop.List; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.PropertySheet; +import com.arsdigita.bebop.PropertySheetModel; +import com.arsdigita.bebop.PropertySheetModelBuilder; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.Tree; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.ChangeEvent; +import com.arsdigita.bebop.event.ChangeListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.PrintEvent; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.bebop.event.FormInitListener; +import com.arsdigita.bebop.list.ListModel; +import com.arsdigita.bebop.list.ListModelBuilder; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.bebop.form.RadioGroup; +import com.arsdigita.bebop.form.Option; +import com.arsdigita.bebop.form.TextField; +import com.arsdigita.bebop.FormData; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.GridPanel; +import com.arsdigita.bebop.tree.TreeModel; +import com.arsdigita.persistence.OID; +import com.arsdigita.bebop.parameters.NotNullValidationListener; +import com.arsdigita.kernel.ui.ACSObjectSelectionModel; +import com.arsdigita.portalserver.PortalSite; +import com.arsdigita.portalserver.PortalSiteCollection; +import com.arsdigita.portalserver.Theme; +import com.arsdigita.portalserver.ThemeCollection; +import com.arsdigita.portalserver.ColorPicker; +import com.arsdigita.xml.Element; +import org.apache.log4j.Logger; +import java.math.BigDecimal; + + + +public class ThemesPane extends SimpleContainer { + + private static final Logger s_log = Logger.getLogger(ThemesPane.class); + + private RadioGroup m_grp; + private Submit createButton; + private SelectThemeForm m_selectForm; + private CreateThemeForm m_createForm; + ActionLink m_createThemeLink; + + public ThemesPane(final RequestLocal portalsiteRL) { + + + m_grp = new RadioGroup("themes"); + m_grp.setClassAttr("vertical"); + + populateOptionGroup(); + + m_selectForm = new SelectThemeForm(portalsiteRL); + m_createForm = new CreateThemeForm(portalsiteRL); + + //m_createThemeLink = new ActionLink( (String) GlobalizationUtil.globalize("portalserver.ui.admin.create_theme").localize()); + //m_createThemeLink.addActionListener(new CreateThemeLinkListener()); + + add(m_selectForm); + add(m_createForm); + //add(m_createThemeLink); + + } + void populateOptionGroup() { + + Option opt; + m_grp.clearOptions(); + ThemeCollection collection = Theme.retrieveAllThemes(); + + while(collection.next()) + { + m_grp.addOption( new Option(collection.getTheme().getID().toString(), + collection.getTheme().getName())); + } + } + + + public class SelectThemeForm extends Form implements FormProcessListener, + FormInitListener + { + private Label instruction; + private Submit button; + RequestLocal prtlRL; + + public SelectThemeForm(RequestLocal portalsiteRL) + { + super("selectthemeform"); + prtlRL = portalsiteRL; + instruction = + new Label(GlobalizationUtil.globalize("portalserver.ui.admin.select_theme_for_portal")); + button = new Submit("selecttheme", + GlobalizationUtil.globalize("portalserver.ui.select_theme")); + button.setButtonLabel("Select Theme"); + + + add(instruction); + add(button); + m_grp.addValidationListener(new NotNullValidationListener("Select a Theme")); + add(m_grp); + addProcessListener(this); + addInitListener(this); + } + public void process(FormSectionEvent e) + { + String selectedkey; + PageState s = e.getPageState(); + + if(button.isSelected(s)) { + selectedkey = (String)m_grp.getValue(s); + BigDecimal bd = + new BigDecimal(selectedkey); + + Theme theme = Theme.retrieveTheme(bd); + + PortalSite p = (PortalSite)prtlRL.get(s); + + p.setTheme(theme); + p.save(); + } + } + public void init(FormSectionEvent e) throws FormProcessException { + PageState ps = e.getPageState(); + if(this.isVisible(ps)) { + //m_createThemeLink.setVisible(ps, true); + m_createForm.setVisible(ps,false); + } + FormData fd = e.getFormData(); + PortalSite p = (PortalSite)prtlRL.get(ps); + Theme theme = p.getTheme(); + if(theme != null) + fd.put("themes",theme.getID().toString()); + + } + + } + + public class CreateThemeForm extends Form implements FormProcessListener, + FormInitListener + { + private Label instruction; + private Submit savebutton; + private Submit cancelbutton; + private TextField themename; + private ColorPicker globalheader; + private ColorPicker globalheadertext; + private ColorPicker background; + private ColorPicker text; + private ColorPicker activetab; + private ColorPicker inactivetab; + private ColorPicker activetabtext; + private ColorPicker inactivetabtext; + private ColorPicker toprule; + private ColorPicker bottomrule; + private ColorPicker portletheader; + private ColorPicker portletborder; + private ColorPicker portletheadertext; + private ColorPicker portletbodynarrow; + RequestLocal prtlRL; + + public CreateThemeForm(RequestLocal portalsiteRL) + { + super("createthemeform"); + prtlRL = portalsiteRL; + setClassAttr("themecreator"); + savebutton = new Submit("savetheme"); + savebutton.setButtonLabel("Save Theme"); + instruction = + new Label(GlobalizationUtil.globalize("portalserver.ui.admin.create_theme_instruction")); + + globalheader = new ColorPicker("Page Header Color ", "#112233"); + globalheadertext = new ColorPicker("Page Header Text Color ", "#112233"); + background = new ColorPicker("Page Background Color ", "#112233"); + text = new ColorPicker("Page Text Color ", "#112233"); + activetab = new ColorPicker("Selected Tab Color ", "#1F22B3"); + inactivetab = new ColorPicker("Unselected Tab Color ", "#112233"); + activetabtext = new ColorPicker("Selected Tab Text Color", "#FFFFFF"); + inactivetabtext = new ColorPicker("Unselected Tab Text Color ", "#11CC33"); + toprule = new ColorPicker("Top Rule Color ", "#FFFFFF"); + bottomrule = new ColorPicker("Bottom Rule Color ", "#FFFFFF"); + portletheader = new ColorPicker("Portlet Header Color ", "#FFFFFF"); + portletborder = new ColorPicker("Portlet Border Color ", "#FFFFFF"); + portletheadertext = new ColorPicker("Portlet Header Text Color ", "#FFFFFF"); + portletbodynarrow = new ColorPicker("Narrow Column Portlet Body Color ", "#FFFFFF"); + + + themename = new TextField("themename"); + themename.addValidationListener(new NotNullValidationListener("Please provide a name for this theme.")); + + add(instruction); + add(themename); + add(background); + add(text); + add(globalheader); + add(globalheadertext); + add(activetab); + add(inactivetab); + add(activetabtext); + add(inactivetabtext); + add(toprule); + add(bottomrule); + add(portletheader); + add(portletheadertext); + add(portletborder); + add(portletbodynarrow); + add(savebutton); + + addProcessListener(this); + addInitListener(this); + } + public void process(FormSectionEvent e) + { + PageState ps = e.getPageState(); + if(savebutton.isSelected(ps)) { + Theme theme = new Theme((String)themename.getValue(ps)); + theme.setActiveTabColor(activetab.getValue(ps)); + theme.setInactiveTabColor(inactivetab.getValue(ps)); + theme.setActiveTabTextColor(activetabtext.getValue(ps)); + theme.setInactiveTabTextColor(inactivetabtext.getValue(ps)); + theme.setTopRuleColor(toprule.getValue(ps)); + theme.setBottomRuleColor(bottomrule.getValue(ps)); + theme.setPortletHeaderColor(portletheader.getValue(ps)); + theme.setPortletIconColor(portletheader.getValue(ps)); + theme.setPortletBorderColor(portletborder.getValue(ps)); + theme.setPortletHeaderTextColor(portletheadertext.getValue(ps)); + theme.setPageBGColor(background.getValue(ps)); + theme.setBodyTextColor(text.getValue(ps)); + theme.setNarrowBGColor(portletbodynarrow.getValue(ps)); + + theme.save(); + } + m_selectForm.setVisible(ps,true); + m_createThemeLink.setVisible(ps, true); + this.setVisible(ps, false); + } + + public void init(FormSectionEvent e) throws FormProcessException { + } + } + private class CreateThemeLinkListener implements ActionListener { + public void actionPerformed(ActionEvent event) { + PageState ps = event.getPageState(); + m_createForm.setVisible(ps,true); + m_selectForm.setVisible(ps,false); + m_createThemeLink.setVisible(ps, false); + } + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/UniquePortalURLValidationListener.java b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/UniquePortalURLValidationListener.java new file mode 100644 index 000000000..f72ad9cde --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/ui/admin/UniquePortalURLValidationListener.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.ui.admin; + +import com.arsdigita.portalserver.*; +import com.arsdigita.bebop.parameters.*; +import com.arsdigita.bebop.event.ParameterEvent; +import com.arsdigita.bebop.event.ParameterListener; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.parameters.ParameterData; + + + +public class UniquePortalURLValidationListener implements ParameterListener { + + public UniquePortalURLValidationListener() { + } + + public void validate(ParameterEvent e) + throws FormProcessException { + + ParameterData d = e.getParameterData(); + String value = (String)d.getValue(); + + + //URLs are stored in DB with leading and trailing slash...make + //sure this URL has them + if(!(value.endsWith("/"))) + value += "/"; + if(!(value.startsWith("/"))) + value = "/" + value; + + PortalSiteCollection pc = PortalSite.retrieveAllPortalSites(); + pc.addEqualsFilter("primaryURL",value); + if(pc.next()) + { + d.invalidate(); + d.addError("Please enter a different URL -- this one has been used"); + } + pc.close(); + } +} diff --git a/ccm-portalserver/src/com/arsdigita/portalserver/util/GlobalizationUtil.java b/ccm-portalserver/src/com/arsdigita/portalserver/util/GlobalizationUtil.java new file mode 100644 index 000000000..a5568b17a --- /dev/null +++ b/ccm-portalserver/src/com/arsdigita/portalserver/util/GlobalizationUtil.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.util; + +import com.arsdigita.globalization.Globalized; +import com.arsdigita.globalization.GlobalizedMessage; + +/** + *

    + * . + * Contains methods to simplify globalizing keys + *

    + * + * @author sarnold@redhat.com + * @version $Revision: #5 $ $Date: 2004/08/17 $ + */ + +public class GlobalizationUtil implements Globalized { + + private static final String BUNDLE_NAME = + "com.arsdigita.portalserver.PortalServerResources"; + + public static GlobalizedMessage globalize(String key) { + return new GlobalizedMessage(key, BUNDLE_NAME); + } + public static GlobalizedMessage globalize(String key, Object[] args) { + return new GlobalizedMessage(key, BUNDLE_NAME, args); + + } +} diff --git a/ccm-portalserver/test/src/com/arsdigita/populate/portalserver/Initializer.java b/ccm-portalserver/test/src/com/arsdigita/populate/portalserver/Initializer.java new file mode 100644 index 000000000..8b0b9308b --- /dev/null +++ b/ccm-portalserver/test/src/com/arsdigita/populate/portalserver/Initializer.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.populate.portalserver; + +import java.util.List; + +import org.apache.log4j.Logger; + +import com.arsdigita.initializer.Configuration; +import com.arsdigita.initializer.InitializationException; +import com.arsdigita.kernel.BaseInitializer; +import com.arsdigita.kernel.UserCollection; +import com.arsdigita.populate.PopulateUsers; +import com.arsdigita.populate.apps.PopulateApp; +import com.arsdigita.populate.apps.PopulateAppPair; +import com.arsdigita.populate.apps.PopulateAppPairCollection; +import com.arsdigita.populate.portlets.PopulatePortlet; +import com.arsdigita.populate.portlets.PopulatePortletCollection; +import com.arsdigita.util.Assert; + +/** + * @author bche + */ +public class Initializer extends BaseInitializer { + private static final Logger s_log = + Logger.getLogger(Initializer.class.getName()); + private Configuration m_conf = new Configuration(); + + /* (non-Javadoc) + * @see com.arsdigita.initializer.Initializer#getConfiguration() + */ + public Configuration getConfiguration() { + m_conf.initParameter("baseStringSeed", + "The base string seed to use for generating String names.", + String.class, + null); + m_conf.initParameter("numUsers", "number of users to create", Integer.class); + m_conf.initParameter("numPortalSiteLevels", "number of levels/depth to nest portal sites", Integer.class); + m_conf.initParameter("numPortalSitesPerLevel", "number of portal sites to create for each level", Integer.class); + m_conf.initParameter( + "populateAppPairs", + "A list pair, consisting of the PopulateApp class with which to populate and" + + "the arguments for that class", + List.class); + m_conf.initParameter("populatePortlets", "A list of PopulatePortlet classes", List.class); + + return m_conf; + } + + /* (non-Javadoc) + * @see com.arsdigita.kernel.BaseInitializer#doStartup() + */ + protected void doStartup() { + String sBaseStringSeed = (String)m_conf.getParameter("baseStringSeed"); + int iUsers = ((Integer) m_conf.getParameter("numUsers")).intValue(); + int iPortalSiteLevels = ((Integer) m_conf.getParameter("numPortalSiteLevels")).intValue(); + int iPortalSitesPerLevel = ((Integer) m_conf.getParameter("numPortalSitesPerLevel")).intValue(); + List popAppsList = (List) m_conf.getParameter("populateAppPairs"); + List popPortletsList = (List) m_conf.getParameter("populatePortlets"); + + if (s_log.isDebugEnabled()) { + s_log.debug("Using BaseStringSeed " + sBaseStringSeed); + } + + //get the popApps + PopulateAppPairCollection popApps = initPopApps(popAppsList); + + //get the popPortlets + PopulatePortletCollection popPortlets = initPopPortlets(popPortletsList); + + //populate users + s_log.info("Begin populating " + iUsers + " users"); + + PopulateUsers popUsers = new PopulateUsers(); + popUsers.setBaseStringSeed(sBaseStringSeed); + popUsers.populate(iUsers); + UserCollection users = popUsers.getPopulatedUsers(); + + s_log.info("End populating " + iUsers + " users"); + + //populate portalserver + s_log.info("Begin populating portal server"); + + PopulatePortalSites popPortals = new PopulatePortalSites(popApps, popPortlets); + popPortals.setBaseStringSeed(sBaseStringSeed); + popPortals.populate(iPortalSiteLevels, iPortalSitesPerLevel, null, users); + + s_log.info("End populating portal server"); + } + + private PopulateAppPairCollection initPopApps(List popAppsList) { + PopulateAppPairCollection popAppsColl = new PopulateAppPairCollection(); + + int iSize = popAppsList.size(); + for (int i = 0; i < iSize; i++) { + List popAppParam = (List) popAppsList.get(i); + // Assert.assertTrue(popAppParam.size() == 2); + Assert.isTrue(popAppParam.size() == 2); + + String sPopApp = (String) popAppParam.get(0); + s_log.debug("PopulateApp is " + sPopApp); + PopulateApp popApp; + try { + popApp = (PopulateApp) Class.forName(sPopApp).newInstance(); + } catch (Exception e) { + throw new InitializationException(e.getMessage()); + } + List args = (List) popAppParam.get(1); + s_log.debug("args are" + args); + PopulateAppPair popAppPair = new PopulateAppPair(popApp, args); + popAppsColl.addPopulateApp(popAppPair); + } + + return popAppsColl; + } + + private PopulatePortletCollection initPopPortlets(List popPortletsList){ + PopulatePortletCollection popPortletsColl = new PopulatePortletCollection(); + + int iSize = popPortletsList.size(); + for (int i=0; i < iSize; i++) { + String sPopPortlet = (String )popPortletsList.get(i); + s_log.debug("PopulatePortlet is " + sPopPortlet); + PopulatePortlet popPortlet; + try { + popPortlet = (PopulatePortlet)Class.forName(sPopPortlet).newInstance(); + } catch (Exception e) { + throw new InitializationException(e.getMessage()); + } + popPortletsColl.addPopulatePortlet(popPortlet); + } + + return popPortletsColl; + } + + /* (non-Javadoc) + * @see com.arsdigita.kernel.BaseInitializer#doShutdown() + */ + protected void doShutdown() { + } + +} diff --git a/ccm-portalserver/test/src/com/arsdigita/populate/portalserver/PopulatePortalSites.java b/ccm-portalserver/test/src/com/arsdigita/populate/portalserver/PopulatePortalSites.java new file mode 100644 index 000000000..c63d582c9 --- /dev/null +++ b/ccm-portalserver/test/src/com/arsdigita/populate/portalserver/PopulatePortalSites.java @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.populate.portalserver; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Iterator; + +import org.apache.log4j.Logger; + +import com.arsdigita.kernel.EmailAddress; +import com.arsdigita.kernel.User; +import com.arsdigita.kernel.UserCollection; +import com.arsdigita.persistence.Session; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.persistence.TransactionContext; +import com.arsdigita.populate.Utilities; +import com.arsdigita.populate.apps.PopulateAppPairCollection; +import com.arsdigita.populate.apps.PopulateApps; +import com.arsdigita.populate.portlets.PopulatePortletCollection; +import com.arsdigita.populate.portlets.PopulatePortlets; +import com.arsdigita.portalserver.PortalSite; +import com.arsdigita.portalserver.PortalTab; +import com.arsdigita.portalserver.PortalTabCollection; + +/** + * @author bche + */ +public class PopulatePortalSites { + private static Logger s_log = Logger.getLogger(PopulatePortalSites.class); + private PopulateAppPairCollection m_popAppPairs = null; + private PopulatePortletCollection m_popPortlets = null; + private String m_sBaseStringSeed = null; + + public PopulatePortalSites( + PopulateAppPairCollection popAppPairs, + PopulatePortletCollection popPortlets) { + m_popAppPairs = popAppPairs; + m_popPortlets = popPortlets; + } + + public void setBaseStringSeed(String sSeed) { + m_sBaseStringSeed = sSeed; + } + + public String getBaseStringSeed() { + return m_sBaseStringSeed; + } + + public void populate( + int iPortalSiteLevels, + int iPortalSitesPerLevel, + PortalSite rootPortal, + UserCollection users) { + Session ses = SessionManager.getSession(); + TransactionContext txn = ses.getTransactionContext(); + + String sBaseName = "Portal" + Utilities.getBaseString(m_sBaseStringSeed); + + // create the portal sites + ArrayList portalSitesList = + new ArrayList(iPortalSiteLevels * iPortalSitesPerLevel); + ArrayList siblings = null; + PortalSite parent = rootPortal; + + for (int i = 0; i < iPortalSiteLevels; i++) { + txn.beginTxn(); + + if (i > 0) { + parent = (PortalSite) siblings.get(0); + } + + siblings = new ArrayList(iPortalSitesPerLevel); + + for (int j = 0; j < iPortalSitesPerLevel; j++) { + String sName = sBaseName + i + j; + PortalSite portal = setupPortalSite(sName, parent, users); + //rewind users so we can use it again + users.rewind(); + s_log.info("created PortalSite " + sName); + if (s_log.isDebugEnabled()) { + String sURL = ""; + PortalSite p = portal; + do { + sURL = p.getTitle() + "/" + sURL; + p = (PortalSite)p.getParentApplication(); + } while (p != null); + s_log.debug("PortalSite " + sName + " has url " + sURL); + } + if (parent != null) { + s_log.info("PortalSite " + sName + " is a child of " + parent.getTitle()); + } + + portalSitesList.add(portal); + siblings.add(portal); + } + //make all the portal sites on this level related to each other + //also make them all the child of a portal site on the previous level + //note that this will make the number of relationsips + //in the system = iPortalSitesPerLevel^2 * iPortalSiteLevels + for (int y = 0; y < siblings.size(); y++) { + PortalSite bro = (PortalSite) siblings.get(y); + + for (int z = 0; z < siblings.size(); z++) { + if (z != y) { + PortalSite sis = (PortalSite) siblings.get(z); + bro.addRelatedPortalSite(sis); + bro.save(); + s_log.info("PortalSite " + bro.getTitle() + " is related to " + sis.getTitle()); + + } + } + } + + txn.commitTxn(); + } + + s_log.info("Adding applications and AppPortlets to PortalSites"); + for (int i=0; i < portalSitesList.size(); i++) { + PopulateApps popApps = new PopulateApps(m_popAppPairs); + popApps.setBaseStringSeed(Utilities.getBaseString(getBaseStringSeed())); + + PopulatePortlets popPortlets = new PopulatePortlets(m_popPortlets); + PortalSite portal = (PortalSite)portalSitesList.get(i); + if (s_log.isDebugEnabled()) { + s_log.debug("adding apps and portlets to PortalSite " + portal.getTitle()); + } + + //get a tab on the portal site to which to add portlets + PortalTabCollection tabs = portal.getTabsForPortalSite(); + tabs.next(); + PortalTab tab = tabs.getPortalTab(); + tabs.close(); + + //create applications and add app portlets + if (s_log.isDebugEnabled()) { + s_log.debug("add apps and ApplicationPortlets to tab " + tab.getTitle()); + } + popApps.populate(1, portal, tab); + + //add portlets to Portaltabs + if (s_log.isDebugEnabled()) { + s_log.debug("add portlets to tab " + tab.getTitle()); + } + popPortlets.populate(1, tab); + } + } + + private PortalSite setupPortalSite(String sName, PortalSite parent, UserCollection users) { + PortalSite portal = PortalSite.createPortalSite(sName, sName, parent); + + //add PortalTabs + int iTabs = 3; + for (int i=0; i < iTabs; i ++) { + PortalTab tab = PortalTab.createTab("Tab" + i); + //use wide layout to ensure compatibility + tab.setLayout("W"); + portal.addPortalTab(tab); + } + + //add members + while (users.next()) { + User user = users.getUser(); + portal.addMember(user); + + String sUser; + Iterator iter = user.getEmailAddresses(); + if (iter.hasNext()){ + sUser = ((EmailAddress)iter.next()).toString(); + } else { + sUser = user.getDisplayName(); + } + s_log.info("added user " + sUser + " to portalsite " + sName); + } + + portal.save(); + return portal; + } +} + diff --git a/ccm-portalserver/test/src/com/arsdigita/populate/portalserver/enterprise.init b/ccm-portalserver/test/src/com/arsdigita/populate/portalserver/enterprise.init new file mode 100644 index 000000000..3a4d4bb2d --- /dev/null +++ b/ccm-portalserver/test/src/com/arsdigita/populate/portalserver/enterprise.init @@ -0,0 +1,55 @@ +// Red Hat Enterprise Portal Server initialization file +// +// When running Portal Server, the parameters for +// com.arsdigita.kernel.Initializer must be modified. +// +// ::login-stylesheet:: -> login_ps_en.xsl +// ::subsite-dispatcher-class:: -> com.arsdigita.portalserver.pslogin.PSSubsiteDispatcher + + +// The following inits are the old way to initialize applications +// and are going to be replaced by new style initializers. +init com.arsdigita.portalserver.OldInitializer { } + +init com.arsdigita.portalserver.admin.Initializer { } + +init com.arsdigita.portalserver.ui.admin.Initializer { } + +init com.arsdigita.portalserver.personal.Initializer { } + + +// The populate code is ot not any use in a production environment +// but only for testing. + +// init com.arsdigita.populate.portalserver.Initializer { +// //Set baseStringSeed to a non-empty value +// //to make all generated Strings in params +// //deterministic rather than random. This will +// //allow you to populate the same values across +// //multiple runs on clean databases. +// baseStringSeed = ""; +// numUsers = 5; +// numPortalSiteLevels = 2; +// numPortalSitesPerLevel = 2; +// populateAppPairs = { +// //populateForum args: numPosts, numMsgs per post +// { "com.arsdigita.forum.PopulateForum", {3, 5}}, +// //populateDocmgr args: numFolderLevels, numFolders, numFiles +// { "com.arsdigita.docmgr.PopulateDocmgr", {3, 2, 2}}, +// //populateFaq args: numQuestions +// { "com.arsdigita.faq.PopulateFaq", {5}}, +// //populateGlossary args: numWords +// { "com.arsdigita.glossary.PopulateGlossary", {5}}, +// //populateBookmarks args: numBookmarks +// { "com.arsdigita.bookmarks.PopulateBookmarks", {5}} +// }; +// populatePortlets = { +// "com.arsdigita.portlets.freeform.PopulateFreeformPortlet", +// "com.arsdigita.portlets.timeofday.PopulateTimeOfDayPortlet", +// "com.arsdigita.portlets.rssfeed.PopulateRSSFeedPortlet", +// "com.arsdigita.populate.portlets.PopulateApplicationDirectoryPortlet", +// "com.arsdigita.populate.portlets.PopulatePortalNavigatorPortlet", +// "com.arsdigita.populate.portlets.PopulatePortalSummaryPortlet", +// "com.arsdigita.populate.portlets.PopulateMyPortalsPortlet" +// }; +// } diff --git a/ccm-portalserver/test/src/com/arsdigita/populate/portlets/AbstractPopulatePSPortlet.java b/ccm-portalserver/test/src/com/arsdigita/populate/portlets/AbstractPopulatePSPortlet.java new file mode 100644 index 000000000..9d81fae0d --- /dev/null +++ b/ccm-portalserver/test/src/com/arsdigita/populate/portlets/AbstractPopulatePSPortlet.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.populate.portlets; + +import org.apache.log4j.Logger; + +import com.arsdigita.persistence.Session; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.persistence.TransactionContext; +import com.arsdigita.portal.Portal; +import com.arsdigita.portal.Portlet; +import com.arsdigita.portal.PortletType; +import com.arsdigita.portal.apportlet.AppPortlet; +import com.arsdigita.portal.apportlet.AppPortletType; +import com.arsdigita.portalserver.PortalSite; +import com.arsdigita.portalserver.PortalTab; +import com.arsdigita.util.Assert; + + +/** + * Abstract class for populating portlets. + * This differs from com.arsdigita.populate.portlets.AbstractPopulatePortlet in that + * it can handle PortalServer AppPortlets as well as normal Portlets. It does this by + * setting the AppPortlet's parent application to the containing PortalSite. + * @author bche + */ +public abstract class AbstractPopulatePSPortlet implements PopulatePortlet { + protected Logger s_log = Logger.getLogger(AbstractPopulatePSPortlet.class); + private Portlet m_portlet = null; + + /* (non-Javadoc) + * @see com.arsdigita.populate.portlets.PopulatePortlet#createPortlet(com.arsdigita.portal.Portal, int) + */ + public void createPortlet(Portal parent, int iCellNumber) { + Session ses = SessionManager.getSession(); + TransactionContext txn = ses.getTransactionContext(); + txn.beginTxn(); + //refresh the portal view so we can save it + parent = Portal.retrieve(parent.getOID()); + + m_portlet = Portlet.createPortlet(getPortletType(), null); + + //check if the portlet is an AppPortlet or a normal Portlet + if (m_portlet instanceof AppPortlet ) { + //this is an AppPortlet, so set its application to the portal site + + //try to get a PortalTab version of the parent + //this will throw a NPE if the Portal is not a PortalTab + PortalTab tab = PortalTab.retrieveTab(parent.getID()); + PortalSite ps = ((PortalTab)tab).getPortalSite(); + + ((AppPortlet)m_portlet).setParentApplication(ps); + + if (s_log.isDebugEnabled()) { + s_log.debug("created AppPortlet: " + m_portlet.getTitle()); + } + } else { + //this is a normal portlet + m_portlet.setParentResource(parent); + + if (s_log.isDebugEnabled()) { + s_log.debug("created normal Portlet: " + m_portlet.getTitle()); + } + } + + //no need to save m_portlet because Portal.afterSave() will save it + parent.addPortlet(m_portlet, iCellNumber); + parent.save(); + txn.commitTxn(); + + //refresh m_portlet so it is available to other txn's + m_portlet = Portlet.retrievePortlet(m_portlet.getOID()); + + } + + /* (non-Javadoc) + * @see com.arsdigita.populate.portlets.PopulatePortlet#populatePortlet() + */ + public abstract void populatePortlet(); + + /* (non-Javadoc) + * @see com.arsdigita.populate.portlets.PopulatePortlet#getPortletType() + */ + public abstract PortletType getPortletType(); + + /* (non-Javadoc) + * @see com.arsdigita.populate.portlets.PopulatePortlet#getPortlet() + */ + public Portlet getPortlet() { + return m_portlet; + } + +} diff --git a/ccm-portalserver/test/src/com/arsdigita/populate/portlets/PopulateApplicationDirectoryPortlet.java b/ccm-portalserver/test/src/com/arsdigita/populate/portlets/PopulateApplicationDirectoryPortlet.java new file mode 100644 index 000000000..8fda67e24 --- /dev/null +++ b/ccm-portalserver/test/src/com/arsdigita/populate/portlets/PopulateApplicationDirectoryPortlet.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.populate.portlets; + +import com.arsdigita.portal.PortletType; +import com.arsdigita.portal.apportlet.AppPortletType; +import com.arsdigita.portalserver.ApplicationDirectoryPortlet; + +/** + * @author bche + */ +public class PopulateApplicationDirectoryPortlet + extends AbstractPopulatePSPortlet + implements PopulatePortlet { + + /* (non-Javadoc) + * @see com.arsdigita.populate.portlets.PopulatePortlet#populatePortlet() + */ + public void populatePortlet() { + //do nothing + } + + /* (non-Javadoc) + * @see com.arsdigita.populate.portlets.PopulatePortlet#getPortletType() + */ + public PortletType getPortletType() { + return (PortletType)AppPortletType.retrievePortletTypeForPortlet(ApplicationDirectoryPortlet.BASE_DATA_OBJECT_TYPE); + } + +} diff --git a/ccm-portalserver/test/src/com/arsdigita/populate/portlets/PopulateMyPortalsPortlet.java b/ccm-portalserver/test/src/com/arsdigita/populate/portlets/PopulateMyPortalsPortlet.java new file mode 100644 index 000000000..56acc610d --- /dev/null +++ b/ccm-portalserver/test/src/com/arsdigita/populate/portlets/PopulateMyPortalsPortlet.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.populate.portlets; + +import com.arsdigita.portal.PortletType; +import com.arsdigita.portal.apportlet.AppPortletType; +import com.arsdigita.portalserver.personal.MyPortalsPortlet; + +/** + * @author bche + */ +public class PopulateMyPortalsPortlet + extends AbstractPopulatePSPortlet + implements PopulatePortlet { + + /* (non-Javadoc) + * @see com.arsdigita.populate.portlets.PopulatePortlet#populatePortlet() + */ + public void populatePortlet() { + //do nothing + } + + /* (non-Javadoc) + * @see com.arsdigita.populate.portlets.PopulatePortlet#getPortletType() + */ + public PortletType getPortletType() { + return (PortletType)AppPortletType.retrievePortletTypeForPortlet(MyPortalsPortlet.BASE_DATA_OBJECT_TYPE); + } + +} diff --git a/ccm-portalserver/test/src/com/arsdigita/populate/portlets/PopulatePortalNavigatorPortlet.java b/ccm-portalserver/test/src/com/arsdigita/populate/portlets/PopulatePortalNavigatorPortlet.java new file mode 100644 index 000000000..253e2008c --- /dev/null +++ b/ccm-portalserver/test/src/com/arsdigita/populate/portlets/PopulatePortalNavigatorPortlet.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.populate.portlets; + +import com.arsdigita.portal.PortletType; +import com.arsdigita.portal.apportlet.AppPortletType; +import com.arsdigita.portalserver.PortalNavigatorPortlet; + +/** + * @author bche + */ +public class PopulatePortalNavigatorPortlet + extends AbstractPopulatePSPortlet + implements PopulatePortlet { + + /* (non-Javadoc) + * @see com.arsdigita.populate.portlets.PopulatePortlet#populatePortlet() + */ + public void populatePortlet() { + //do nothing + } + + /* (non-Javadoc) + * @see com.arsdigita.populate.portlets.PopulatePortlet#getPortletType() + */ + public PortletType getPortletType() { + return (PortletType)AppPortletType.retrievePortletTypeForPortlet(PortalNavigatorPortlet.BASE_DATA_OBJECT_TYPE); + } + +} diff --git a/ccm-portalserver/test/src/com/arsdigita/populate/portlets/PopulatePortalSummaryPortlet.java b/ccm-portalserver/test/src/com/arsdigita/populate/portlets/PopulatePortalSummaryPortlet.java new file mode 100644 index 000000000..1c3ac589c --- /dev/null +++ b/ccm-portalserver/test/src/com/arsdigita/populate/portlets/PopulatePortalSummaryPortlet.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.populate.portlets; + +import com.arsdigita.portal.PortletType; +import com.arsdigita.portal.apportlet.AppPortletType; +import com.arsdigita.portalserver.PortalSummaryPortlet; + +/** + * @author bche + */ +public class PopulatePortalSummaryPortlet + extends AbstractPopulatePSPortlet + implements PopulatePortlet { + + /* (non-Javadoc) + * @see com.arsdigita.populate.portlets.PopulatePortlet#populatePortlet() + */ + public void populatePortlet() { + //do nothing + } + + /* (non-Javadoc) + * @see com.arsdigita.populate.portlets.PopulatePortlet#getPortletType() + */ + public PortletType getPortletType() { + return (PortletType)AppPortletType.retrievePortletTypeForPortlet(PortalSummaryPortlet.BASE_DATA_OBJECT_TYPE); + } + +} diff --git a/ccm-portalserver/test/src/com/arsdigita/test/Initializer.java b/ccm-portalserver/test/src/com/arsdigita/test/Initializer.java new file mode 100644 index 000000000..faca8cbb5 --- /dev/null +++ b/ccm-portalserver/test/src/com/arsdigita/test/Initializer.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.test; + +import com.arsdigita.initializer.Configuration; +import com.arsdigita.initializer.InitializationException; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.persistence.TransactionContext; +import com.arsdigita.kernel.*; +import com.arsdigita.portalserver.*; + + +import org.apache.log4j.Category; + +public class Initializer implements com.arsdigita.initializer.Initializer { + public Configuration getConfiguration() { + return null; + } + + public void startup() throws InitializationException { + s_log.warn("Initializing Portal..."); + + TransactionContext txn = + SessionManager.getSession().getTransactionContext(); + + txn.beginTxn(); + + TestPortalSetup setup = new TestPortalSetup(); + setup.setupPortal(); + txn.commitTxn(); + + } + + public void shutdown() throws InitializationException { + + } + + private static Category s_log = Category.getInstance + (Initializer.class); + + private Configuration m_conf = new Configuration(); + + + + +} diff --git a/ccm-portalserver/test/src/com/arsdigita/test/TestApps.java b/ccm-portalserver/test/src/com/arsdigita/test/TestApps.java new file mode 100644 index 000000000..e82c6026b --- /dev/null +++ b/ccm-portalserver/test/src/com/arsdigita/test/TestApps.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.test; + +import com.arsdigita.kernel.EmailAddress; + +public final class TestApps { + public static final String KM_MANAGER = "Knowledge Manager"; + public static final String DOC_MANAGER = "Document Manager"; + public static final String FORUM = "Forum"; + public static final String PORTAL = "test"; + + public static final String MANAGERS = "Managers"; + public static final String EDITORS = "Editors"; + public static final String MEMBERS = "Members"; + + public static final String DEFAULT_DOMAIN = "redhat.com"; + + public static final EmailAddress SWA = new EmailAddress("swa@" + DEFAULT_DOMAIN); + public static final EmailAddress USER = new EmailAddress("joeuser@" + DEFAULT_DOMAIN); + public static final EmailAddress MANAGER = new EmailAddress("joemanager@" + DEFAULT_DOMAIN); + public static final EmailAddress EDITOR = new EmailAddress("joeeditor@" + DEFAULT_DOMAIN); + + private TestApps() { + } +} diff --git a/ccm-portalserver/test/src/com/arsdigita/test/TestPortalSetup.java b/ccm-portalserver/test/src/com/arsdigita/test/TestPortalSetup.java new file mode 100644 index 000000000..aba03c144 --- /dev/null +++ b/ccm-portalserver/test/src/com/arsdigita/test/TestPortalSetup.java @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.portalserver.test; + +import com.arsdigita.kernel.permissions.PermissionDescriptor; +import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; +import com.arsdigita.kernel.*; +import com.arsdigita.web.*; +import com.arsdigita.portal.Portlet; +import com.arsdigita.portalserver.*; +import com.arsdigita.portalserver.Role; + + +import org.apache.log4j.Logger; + +public class TestPortalSetup { + + + private static Logger s_log = Logger.getLogger(TestPortalSetup.class); + private PortalSite m_portalsite; + private Party m_member; + private Party m_editor; + private Party m_manager; + + private Role m_members; + private Role m_editors; + private Role m_managers; + + + public void setupPortal() { + + s_log.warn("Calling setupPortal"); + if( portalDoesNotExist() ) { + s_log.warn("Creating test portal titled: " + TestApps.PORTAL); + setupDefaultPortal(); + setupDefaultRoles(); + setupDefaultUsers(); + } + } + + + private boolean portalDoesNotExist() { + s_log.warn("Checking for portals!"); + PortalSiteCollection psites = PortalSite.retrieveAllPortalSites(); + boolean doesNotExist = true; + int portalCount = 0; + try { + s_log.warn("Starting loop!"); + while(psites.next() && doesNotExist) { + String title = psites.getTitle(); + s_log.warn("Portal: " + title); + doesNotExist = !title.equals(TestApps.PORTAL); + portalCount++; + } + } finally { + psites.close(); + } + + s_log.warn("Portal count: " + portalCount); + return doesNotExist; + } + /** + * Creates a new role for a portalsite with Read-Only access. + * + * @param portalsite The portalsite to add the role to. + * @param roleName The name of the role. + * @param assigneeTitle The tile of people assigned to the role. + * @param description A description of the role. + * + * @return The newly created role. + */ + private Role createRole(PortalSite portalsite, + String roleName, + String assigneeTitle, + String description) { + + Role newRole = createRole(portalsite, + roleName, + assigneeTitle, + description, + PrivilegeDescriptor.READ); + + return newRole; + + } + + /** + * Creates a new role for a portalsite. + * + * @param portalsite The portalsite to add the role to. + * @param roleName The name of the role. + * @param assigneeTitle The tile of people assigned to the role. + * @param description A description of the role. + * @param privilege The privilege to grant this role on the workspace. + * + * @return The newly created role. + */ + private Role createRole(PortalSite portalsite, + String roleName, + String assigneeTitle, + String description, + PrivilegeDescriptor privilege) { + Role newRole = + Role.createRole(portalsite, + roleName, assigneeTitle, description); + newRole.save(); + + + PermissionService.grantPermission( + new PermissionDescriptor(PrivilegeDescriptor.CREATE, portalsite, + newRole)); + + PermissionService.grantPermission( + new PermissionDescriptor(privilege, + portalsite, + newRole)); + + return newRole; + + } + + + private void setupDefaultPortal() { + m_portalsite = PortalSite.createPortalSite(TestApps.PORTAL, "test", null); + m_portalsite.save(); + + // By default, add some portlets. + PortalTab mainTab = PortalTab.createTab("Main"); + + Portlet portlet = Portlet.createPortlet + (ApplicationDirectoryPortlet.BASE_DATA_OBJECT_TYPE, m_portalsite); + mainTab.addPortlet(portlet, 1); + + portlet = Portlet.createPortlet + (PortalNavigatorPortlet.BASE_DATA_OBJECT_TYPE, m_portalsite); + mainTab.addPortlet(portlet, 1); + + portlet = Portlet.createPortlet + (PortalSummaryPortlet.BASE_DATA_OBJECT_TYPE, m_portalsite); + mainTab.addPortlet(portlet, 1); + + + mainTab.setPortalSite(m_portalsite); + mainTab.save(); + m_portalsite.addPortalTab(mainTab); + m_portalsite.save(); + + } + + private Application addApplication(String applicationObjectType, String urlName, String title) { + Application app = Application.createApplication(applicationObjectType, urlName, title, m_portalsite); + app.save(); + + return app; + } + + private void setupDefaultUsers() { + m_member = createUser("Joe", "User"); + m_editor = createUser("Joe", "Editor"); + + m_manager = createUser("Joe", "Manager"); + + m_portalsite.addParticipant(m_member); + m_portalsite.addParticipant(m_editor); + m_portalsite.addParticipant(m_manager); + + m_portalsite.save(); + + m_members.addMemberOrSubgroup(m_member); + m_members.save(); + m_editors.addMemberOrSubgroup(m_editor); + m_editors.save(); + m_managers.addMemberOrSubgroup(m_manager); + m_managers.save(); + + } + + private User createUser(String firstName, String lastName) { + String firstLast = firstName.trim().toLowerCase() + lastName.trim().toLowerCase(); + EmailAddress email = new EmailAddress(firstLast + "@" + TestApps.DEFAULT_DOMAIN); + User user = UserFactory.newUser(email, firstName, lastName, firstLast, firstLast, firstLast, null, null, null); + user.save(); + return user; + + } + private void setupDefaultRoles() { + + m_members = m_portalsite.getMemberRole(); + + m_editors = createRole(m_portalsite, "Editors", "Editor", "", PrivilegeDescriptor.EDIT); + m_managers = createRole(m_portalsite, "Managers", "Manager", "", PrivilegeDescriptor.ADMIN); + + + } + + +} diff --git a/ccm-portalserver/web/__ccm__/apps/personal-portal-creator/xsl/index.xsl b/ccm-portalserver/web/__ccm__/apps/personal-portal-creator/xsl/index.xsl new file mode 100644 index 000000000..b8f31b3f8 --- /dev/null +++ b/ccm-portalserver/web/__ccm__/apps/personal-portal-creator/xsl/index.xsl @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/ccm-portalserver/web/__ccm__/apps/personal-portal/xsl/index.xsl b/ccm-portalserver/web/__ccm__/apps/personal-portal/xsl/index.xsl new file mode 100644 index 000000000..b8f31b3f8 --- /dev/null +++ b/ccm-portalserver/web/__ccm__/apps/personal-portal/xsl/index.xsl @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/ccm-portalserver/web/__ccm__/apps/portal-admin/xsl/index.xsl b/ccm-portalserver/web/__ccm__/apps/portal-admin/xsl/index.xsl new file mode 100644 index 000000000..b8f31b3f8 --- /dev/null +++ b/ccm-portalserver/web/__ccm__/apps/portal-admin/xsl/index.xsl @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/ccm-portalserver/web/__ccm__/apps/portal-archive/xsl/index.xsl b/ccm-portalserver/web/__ccm__/apps/portal-archive/xsl/index.xsl new file mode 100644 index 000000000..b8f31b3f8 --- /dev/null +++ b/ccm-portalserver/web/__ccm__/apps/portal-archive/xsl/index.xsl @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/ccm-portalserver/web/__ccm__/apps/portal-create/xsl/index.xsl b/ccm-portalserver/web/__ccm__/apps/portal-create/xsl/index.xsl new file mode 100644 index 000000000..b8f31b3f8 --- /dev/null +++ b/ccm-portalserver/web/__ccm__/apps/portal-create/xsl/index.xsl @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/ccm-portalserver/web/__ccm__/apps/portal-sitemap/xsl/index.xsl b/ccm-portalserver/web/__ccm__/apps/portal-sitemap/xsl/index.xsl new file mode 100644 index 000000000..b521fc471 --- /dev/null +++ b/ccm-portalserver/web/__ccm__/apps/portal-sitemap/xsl/index.xsl @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/ccm-portalserver/web/__ccm__/apps/portalsite/xsl/index.xsl b/ccm-portalserver/web/__ccm__/apps/portalsite/xsl/index.xsl new file mode 100644 index 000000000..b8f31b3f8 --- /dev/null +++ b/ccm-portalserver/web/__ccm__/apps/portalsite/xsl/index.xsl @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/ccm-portalserver/web/assets/cw/NNN_off.gif b/ccm-portalserver/web/assets/cw/NNN_off.gif new file mode 100644 index 000000000..c4ee44104 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/NNN_off.gif differ diff --git a/ccm-portalserver/web/assets/cw/NNN_off.png b/ccm-portalserver/web/assets/cw/NNN_off.png new file mode 100644 index 000000000..1548f4720 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/NNN_off.png differ diff --git a/ccm-portalserver/web/assets/cw/NNN_on.gif b/ccm-portalserver/web/assets/cw/NNN_on.gif new file mode 100644 index 000000000..c3bd22d70 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/NNN_on.gif differ diff --git a/ccm-portalserver/web/assets/cw/NNN_on.png b/ccm-portalserver/web/assets/cw/NNN_on.png new file mode 100644 index 000000000..e08c59c26 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/NNN_on.png differ diff --git a/ccm-portalserver/web/assets/cw/NWN_off.gif b/ccm-portalserver/web/assets/cw/NWN_off.gif new file mode 100644 index 000000000..b585f0f9b Binary files /dev/null and b/ccm-portalserver/web/assets/cw/NWN_off.gif differ diff --git a/ccm-portalserver/web/assets/cw/NWN_off.png b/ccm-portalserver/web/assets/cw/NWN_off.png new file mode 100644 index 000000000..6f43e0422 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/NWN_off.png differ diff --git a/ccm-portalserver/web/assets/cw/NWN_on.gif b/ccm-portalserver/web/assets/cw/NWN_on.gif new file mode 100644 index 000000000..596bfe177 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/NWN_on.gif differ diff --git a/ccm-portalserver/web/assets/cw/NWN_on.png b/ccm-portalserver/web/assets/cw/NWN_on.png new file mode 100644 index 000000000..4d7e47785 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/NWN_on.png differ diff --git a/ccm-portalserver/web/assets/cw/NW_off.gif b/ccm-portalserver/web/assets/cw/NW_off.gif new file mode 100644 index 000000000..ca74394da Binary files /dev/null and b/ccm-portalserver/web/assets/cw/NW_off.gif differ diff --git a/ccm-portalserver/web/assets/cw/NW_off.png b/ccm-portalserver/web/assets/cw/NW_off.png new file mode 100644 index 000000000..ea02b3b49 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/NW_off.png differ diff --git a/ccm-portalserver/web/assets/cw/NW_on.gif b/ccm-portalserver/web/assets/cw/NW_on.gif new file mode 100644 index 000000000..f7f0825fa Binary files /dev/null and b/ccm-portalserver/web/assets/cw/NW_on.gif differ diff --git a/ccm-portalserver/web/assets/cw/NW_on.png b/ccm-portalserver/web/assets/cw/NW_on.png new file mode 100644 index 000000000..a27fb111f Binary files /dev/null and b/ccm-portalserver/web/assets/cw/NW_on.png differ diff --git a/ccm-portalserver/web/assets/cw/WN_off.gif b/ccm-portalserver/web/assets/cw/WN_off.gif new file mode 100644 index 000000000..aeb65d38d Binary files /dev/null and b/ccm-portalserver/web/assets/cw/WN_off.gif differ diff --git a/ccm-portalserver/web/assets/cw/WN_off.png b/ccm-portalserver/web/assets/cw/WN_off.png new file mode 100644 index 000000000..f4463e401 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/WN_off.png differ diff --git a/ccm-portalserver/web/assets/cw/WN_on.gif b/ccm-portalserver/web/assets/cw/WN_on.gif new file mode 100644 index 000000000..49f22fe51 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/WN_on.gif differ diff --git a/ccm-portalserver/web/assets/cw/WN_on.png b/ccm-portalserver/web/assets/cw/WN_on.png new file mode 100644 index 000000000..a9590f52b Binary files /dev/null and b/ccm-portalserver/web/assets/cw/WN_on.png differ diff --git a/ccm-portalserver/web/assets/cw/W_off.gif b/ccm-portalserver/web/assets/cw/W_off.gif new file mode 100644 index 000000000..bd355b9b9 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/W_off.gif differ diff --git a/ccm-portalserver/web/assets/cw/W_off.png b/ccm-portalserver/web/assets/cw/W_off.png new file mode 100644 index 000000000..07d11fc72 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/W_off.png differ diff --git a/ccm-portalserver/web/assets/cw/W_on.gif b/ccm-portalserver/web/assets/cw/W_on.gif new file mode 100644 index 000000000..00f5e4d53 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/W_on.gif differ diff --git a/ccm-portalserver/web/assets/cw/W_on.png b/ccm-portalserver/web/assets/cw/W_on.png new file mode 100644 index 000000000..a370d571f Binary files /dev/null and b/ccm-portalserver/web/assets/cw/W_on.png differ diff --git a/ccm-portalserver/web/assets/cw/action-link.gif b/ccm-portalserver/web/assets/cw/action-link.gif new file mode 100644 index 000000000..4e36a6d03 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/action-link.gif differ diff --git a/ccm-portalserver/web/assets/cw/backgrounds/bg_bos.gif b/ccm-portalserver/web/assets/cw/backgrounds/bg_bos.gif new file mode 100644 index 000000000..4c3ca982b Binary files /dev/null and b/ccm-portalserver/web/assets/cw/backgrounds/bg_bos.gif differ diff --git a/ccm-portalserver/web/assets/cw/backgrounds/ncc_back.jpg b/ccm-portalserver/web/assets/cw/backgrounds/ncc_back.jpg new file mode 100644 index 000000000..6a5052f04 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/backgrounds/ncc_back.jpg differ diff --git a/ccm-portalserver/web/assets/cw/backgrounds/stars.gif b/ccm-portalserver/web/assets/cw/backgrounds/stars.gif new file mode 100644 index 000000000..d3e0f4971 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/backgrounds/stars.gif differ diff --git a/ccm-portalserver/web/assets/cw/calendar.gif b/ccm-portalserver/web/assets/cw/calendar.gif new file mode 100644 index 000000000..d7ab2c6f8 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/calendar.gif differ diff --git a/ccm-portalserver/web/assets/cw/checked.gif b/ccm-portalserver/web/assets/cw/checked.gif new file mode 100644 index 000000000..abfe86602 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/checked.gif differ diff --git a/ccm-portalserver/web/assets/cw/configure-16.gif b/ccm-portalserver/web/assets/cw/configure-16.gif new file mode 100644 index 000000000..bd02c55bb Binary files /dev/null and b/ccm-portalserver/web/assets/cw/configure-16.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/add.gif b/ccm-portalserver/web/assets/cw/general/add.gif new file mode 100644 index 000000000..834db81c8 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/add.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/copy.gif b/ccm-portalserver/web/assets/cw/general/copy.gif new file mode 100644 index 000000000..632ae4bb0 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/copy.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/delete.gif b/ccm-portalserver/web/assets/cw/general/delete.gif new file mode 100644 index 000000000..30f8bd37c Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/delete.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/down.gif b/ccm-portalserver/web/assets/cw/general/down.gif new file mode 100644 index 000000000..961446b02 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/down.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/edit.gif b/ccm-portalserver/web/assets/cw/general/edit.gif new file mode 100644 index 000000000..0a906dca1 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/edit.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/green-dot.gif b/ccm-portalserver/web/assets/cw/general/green-dot.gif new file mode 100644 index 000000000..c51af6103 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/green-dot.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/help.gif b/ccm-portalserver/web/assets/cw/general/help.gif new file mode 100644 index 000000000..7f13f3fb9 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/help.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/high-urgency.gif b/ccm-portalserver/web/assets/cw/general/high-urgency.gif new file mode 100644 index 000000000..ef8ae1387 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/high-urgency.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/left.gif b/ccm-portalserver/web/assets/cw/general/left.gif new file mode 100644 index 000000000..dc96e1b10 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/left.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/link.gif b/ccm-portalserver/web/assets/cw/general/link.gif new file mode 100644 index 000000000..02f26e5f5 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/link.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/medium-urgency.gif b/ccm-portalserver/web/assets/cw/general/medium-urgency.gif new file mode 100644 index 000000000..0e0c23c89 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/medium-urgency.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/move.gif b/ccm-portalserver/web/assets/cw/general/move.gif new file mode 100644 index 000000000..8712d2256 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/move.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/no-urgency.gif b/ccm-portalserver/web/assets/cw/general/no-urgency.gif new file mode 100644 index 000000000..feaa38517 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/no-urgency.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/red-dot.gif b/ccm-portalserver/web/assets/cw/general/red-dot.gif new file mode 100644 index 000000000..95c16d61e Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/red-dot.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/right.gif b/ccm-portalserver/web/assets/cw/general/right.gif new file mode 100644 index 000000000..5720bba91 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/right.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/search.gif b/ccm-portalserver/web/assets/cw/general/search.gif new file mode 100644 index 000000000..fd18a7b72 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/search.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/sign-out.gif b/ccm-portalserver/web/assets/cw/general/sign-out.gif new file mode 100644 index 000000000..2b3b3ad0e Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/sign-out.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/spacer.gif b/ccm-portalserver/web/assets/cw/general/spacer.gif new file mode 100644 index 000000000..1d11fa9ad Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/spacer.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/up.gif b/ccm-portalserver/web/assets/cw/general/up.gif new file mode 100644 index 000000000..c1e46b1d7 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/up.gif differ diff --git a/ccm-portalserver/web/assets/cw/general/yellow-dot.gif b/ccm-portalserver/web/assets/cw/general/yellow-dot.gif new file mode 100644 index 000000000..d1dc247d4 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/general/yellow-dot.gif differ diff --git a/ccm-portalserver/web/assets/cw/group-16.gif b/ccm-portalserver/web/assets/cw/group-16.gif new file mode 100644 index 000000000..8b00ec1d9 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/group-16.gif differ diff --git a/ccm-portalserver/web/assets/cw/group-32.gif b/ccm-portalserver/web/assets/cw/group-32.gif new file mode 100644 index 000000000..8286d1786 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/group-32.gif differ diff --git a/ccm-portalserver/web/assets/cw/group.gif b/ccm-portalserver/web/assets/cw/group.gif new file mode 100644 index 000000000..8b00ec1d9 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/group.gif differ diff --git a/ccm-portalserver/web/assets/cw/help.gif b/ccm-portalserver/web/assets/cw/help.gif new file mode 100644 index 000000000..dc5c2d310 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/help.gif differ diff --git a/ccm-portalserver/web/assets/cw/personal-16.gif b/ccm-portalserver/web/assets/cw/personal-16.gif new file mode 100644 index 000000000..aad8fe70b Binary files /dev/null and b/ccm-portalserver/web/assets/cw/personal-16.gif differ diff --git a/ccm-portalserver/web/assets/cw/personal-32.gif b/ccm-portalserver/web/assets/cw/personal-32.gif new file mode 100644 index 000000000..6cc6c7a39 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/personal-32.gif differ diff --git a/ccm-portalserver/web/assets/cw/remove.gif b/ccm-portalserver/web/assets/cw/remove.gif new file mode 100644 index 000000000..c1b4ca11d Binary files /dev/null and b/ccm-portalserver/web/assets/cw/remove.gif differ diff --git a/ccm-portalserver/web/assets/cw/signout.gif b/ccm-portalserver/web/assets/cw/signout.gif new file mode 100644 index 000000000..064202bf3 Binary files /dev/null and b/ccm-portalserver/web/assets/cw/signout.gif differ diff --git a/ccm-portalserver/web/assets/cw/unchecked.gif b/ccm-portalserver/web/assets/cw/unchecked.gif new file mode 100644 index 000000000..2ef997f1c Binary files /dev/null and b/ccm-portalserver/web/assets/cw/unchecked.gif differ diff --git a/ccm-portalserver/web/assets/cw/user.gif b/ccm-portalserver/web/assets/cw/user.gif new file mode 100644 index 000000000..aad8fe70b Binary files /dev/null and b/ccm-portalserver/web/assets/cw/user.gif differ diff --git a/ccm-portalserver/web/assets/portalserver/action-add.gif b/ccm-portalserver/web/assets/portalserver/action-add.gif new file mode 100644 index 000000000..d55fdef9d Binary files /dev/null and b/ccm-portalserver/web/assets/portalserver/action-add.gif differ diff --git a/ccm-portalserver/web/assets/portalserver/archive.gif b/ccm-portalserver/web/assets/portalserver/archive.gif new file mode 100644 index 000000000..45517c2ba Binary files /dev/null and b/ccm-portalserver/web/assets/portalserver/archive.gif differ diff --git a/ccm-portalserver/web/assets/portalserver/delete.gif b/ccm-portalserver/web/assets/portalserver/delete.gif new file mode 100644 index 000000000..30f8bd37c Binary files /dev/null and b/ccm-portalserver/web/assets/portalserver/delete.gif differ diff --git a/ccm-portalserver/web/assets/portalserver/edit.gif b/ccm-portalserver/web/assets/portalserver/edit.gif new file mode 100644 index 000000000..ad930662b Binary files /dev/null and b/ccm-portalserver/web/assets/portalserver/edit.gif differ diff --git a/ccm-portalserver/web/packages/login/xsl/login_ps_en.xsl b/ccm-portalserver/web/packages/login/xsl/login_ps_en.xsl new file mode 100644 index 000000000..8588bf2fb --- /dev/null +++ b/ccm-portalserver/web/packages/login/xsl/login_ps_en.xsl @@ -0,0 +1,63 @@ + + + + + + + +
    + +

    Our server can tell your browser to remember certain things, such as your +email address and password. This is convenient for you because, if you're +the only person who uses your computer, you won't have to keep telling us +your email address and password.

    + +

    It would be a very bad idea to choose this option if you're using a +shared computer in a library or school. Any subsequent user of this machine +would be able to masquerade as you on our service.

    + +

    Note that you can erase your saved email address and password by choosing +the "log out" option from your workspace.

    +
    + + +

    Current users: Please enter your email and password below.

    + +

    New users: Please +begin the registration process by entering a valid email address and leaving +the password field blank. We will direct you to another form to complete +your registration.

    +
    + + +

    If you keep getting thrown back here, it is probably because your +browser does not accept cookies.

    +
    + + +

    You have been sent an email that will allow you to change your +password.

    +
    + + +

    Unable to send password recovery information via email.

    +

    Please contact the system administrator for further help in recovering your password.

    +
    + + +

    + +
    + + + +
    Note: For security reasons, the login page +expires after a certain interval to prevent malicious attackers from logging +in as you using cached browser passwords.
    + + + + diff --git a/ccm-portalserver/web/packages/portalserver/www/assets/CheckEmpty16.gif b/ccm-portalserver/web/packages/portalserver/www/assets/CheckEmpty16.gif new file mode 100644 index 000000000..b33dfe7fd Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/assets/CheckEmpty16.gif differ diff --git a/ccm-portalserver/web/packages/portalserver/www/assets/CheckFull16.gif b/ccm-portalserver/web/packages/portalserver/www/assets/CheckFull16.gif new file mode 100644 index 000000000..0d5cfd5c1 Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/assets/CheckFull16.gif differ diff --git a/ccm-portalserver/web/packages/portalserver/www/assets/Delete16.gif b/ccm-portalserver/web/packages/portalserver/www/assets/Delete16.gif new file mode 100644 index 000000000..d9d1a338f Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/assets/Delete16.gif differ diff --git a/ccm-portalserver/web/packages/portalserver/www/assets/Down16.gif b/ccm-portalserver/web/packages/portalserver/www/assets/Down16.gif new file mode 100644 index 000000000..39849181f Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/assets/Down16.gif differ diff --git a/ccm-portalserver/web/packages/portalserver/www/assets/Group16.gif b/ccm-portalserver/web/packages/portalserver/www/assets/Group16.gif new file mode 100644 index 000000000..96e1d9eb7 Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/assets/Group16.gif differ diff --git a/ccm-portalserver/web/packages/portalserver/www/assets/Left16.gif b/ccm-portalserver/web/packages/portalserver/www/assets/Left16.gif new file mode 100644 index 000000000..5395ea8a9 Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/assets/Left16.gif differ diff --git a/ccm-portalserver/web/packages/portalserver/www/assets/Properties16.gif b/ccm-portalserver/web/packages/portalserver/www/assets/Properties16.gif new file mode 100644 index 000000000..c0c3d4326 Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/assets/Properties16.gif differ diff --git a/ccm-portalserver/web/packages/portalserver/www/assets/RadioEmpty16.gif b/ccm-portalserver/web/packages/portalserver/www/assets/RadioEmpty16.gif new file mode 100644 index 000000000..c523e56e0 Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/assets/RadioEmpty16.gif differ diff --git a/ccm-portalserver/web/packages/portalserver/www/assets/RadioEmptyGrayed16.gif b/ccm-portalserver/web/packages/portalserver/www/assets/RadioEmptyGrayed16.gif new file mode 100644 index 000000000..ee1ba4cc9 Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/assets/RadioEmptyGrayed16.gif differ diff --git a/ccm-portalserver/web/packages/portalserver/www/assets/RadioFull16.gif b/ccm-portalserver/web/packages/portalserver/www/assets/RadioFull16.gif new file mode 100644 index 000000000..7366c6286 Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/assets/RadioFull16.gif differ diff --git a/ccm-portalserver/web/packages/portalserver/www/assets/RadioFullGrayed16.gif b/ccm-portalserver/web/packages/portalserver/www/assets/RadioFullGrayed16.gif new file mode 100644 index 000000000..c95fe819d Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/assets/RadioFullGrayed16.gif differ diff --git a/ccm-portalserver/web/packages/portalserver/www/assets/Right16.gif b/ccm-portalserver/web/packages/portalserver/www/assets/Right16.gif new file mode 100644 index 000000000..a89091bc7 Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/assets/Right16.gif differ diff --git a/ccm-portalserver/web/packages/portalserver/www/assets/Up16.gif b/ccm-portalserver/web/packages/portalserver/www/assets/Up16.gif new file mode 100644 index 000000000..cebe60d95 Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/assets/Up16.gif differ diff --git a/ccm-portalserver/web/packages/portalserver/www/assets/User16.gif b/ccm-portalserver/web/packages/portalserver/www/assets/User16.gif new file mode 100644 index 000000000..187a50f9a Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/assets/User16.gif differ diff --git a/ccm-portalserver/web/packages/portalserver/www/assets/ZoomIn16.gif b/ccm-portalserver/web/packages/portalserver/www/assets/ZoomIn16.gif new file mode 100644 index 000000000..2329426e4 Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/assets/ZoomIn16.gif differ diff --git a/ccm-portalserver/web/packages/portalserver/www/assets/help.gif b/ccm-portalserver/web/packages/portalserver/www/assets/help.gif new file mode 100644 index 000000000..0f69f633f Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/assets/help.gif differ diff --git a/ccm-portalserver/web/packages/portalserver/www/assets/left-on.gif b/ccm-portalserver/web/packages/portalserver/www/assets/left-on.gif new file mode 100644 index 000000000..5010f36e0 Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/assets/left-on.gif differ diff --git a/ccm-portalserver/web/packages/portalserver/www/css/RHCLogoRoundRedSmallest.png b/ccm-portalserver/web/packages/portalserver/www/css/RHCLogoRoundRedSmallest.png new file mode 100644 index 000000000..43979025f Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/css/RHCLogoRoundRedSmallest.png differ diff --git a/ccm-portalserver/web/packages/portalserver/www/css/portal-sitemap.css b/ccm-portalserver/web/packages/portalserver/www/css/portal-sitemap.css new file mode 100644 index 000000000..db243b6ef --- /dev/null +++ b/ccm-portalserver/web/packages/portalserver/www/css/portal-sitemap.css @@ -0,0 +1,109 @@ +@import url("/css/acs-master.css"); + +body, td, th, div, p { + font-family: sans-serif; + font-size: 12px; + cursor: default; +} +body { + color: #000; + padding: 0; + margin: 0; + /* background: #fff url(/img/bg-drift.gif) top repeat-x; */ + background-color: #fff; +} + +table.details-2-columns { + padding: 4; + border: none; +} + +table.details { + margin: 0 2%; +} + +.details th { + padding: 8px; + padding-left: 16px; + border: none; + color: #444; + text-align: right; + vertical-align: top; + border: 1px solid #ddd; + border:none; + background-color: #eee; + -moz-border-radius-topleft: 15px; + -moz-border-radius-bottomleft: 15px; +} + +.details th.required-form-field { + border-right: 4px solid #c77; +} + +.details td { + vertical-align: top; + padding: 4px; + padding-left: 2px; + padding: 8px; + border-bottom: 0; +} + +.details th + td { + border-bottom: 1px solid #ddd; +} + +.details td div { + text-align: left; + margin-bottom: 10px; + white-space: nowrap; +} + +.details td table td { + margin: 0; + padding: 0; + border: 0; +} + +.details td table { +} + +table.details td.small-form textarea { + font-size: 10px; + font-family: monospace; +} + +.details-header { + font-weight: bold; + /* + */ + color: #444; + font-family: helvetica; +} + +td.heading_cell { + font-size: 12px; + font-weight: bold; + font-family: sans-serif; + color:#999; + border-bottom: 2px solid #ccc; +} + +table.sitemaplinks { + border-top: 2px double #aaa; +} + +table.sitemapdelete { + border-top: 2px double #aaa; +} + +table.sitemapdeleteappstable { + border: 2px double #aaa; +} + +tr.deleteeven { + background-color: #fff; +} + +tr.deleteodd { + background-color: #eee; +} diff --git a/ccm-portalserver/web/packages/portalserver/www/css/portalserver.css b/ccm-portalserver/web/packages/portalserver/www/css/portalserver.css new file mode 100644 index 000000000..73276614d --- /dev/null +++ b/ccm-portalserver/web/packages/portalserver/www/css/portalserver.css @@ -0,0 +1,734 @@ +/* + * Fundamental Styles + */ + +body { + background-color: white; + font-family: Arial, Helvetica, sans-serif; + font-size: 10pt; + margin: 0; +} + +table { + border-spacing: 0; + empty-cells: show; +} + +td { + font-family: Arial, Helvetica, sans-serif; + font-size: 10pt; + vertical-align: top; +} + +.main { /* background-color: #ffffff; */ } +.dark { /* background-color: #666666; */ } +.medium { /* background-color: #999999; */ } +.light { /* background-color: #cccccc; */ } + +.activeTabColor { + background: #A2E1E1; +} + +.inactiveTabColor { + background: #E1E1E1; +} + +.dialogTitle { + font-weight: bold; + font-size: 12pt; +} + +.messageOfTheDay { + padding-left: 0.4em; + padding-right: 0.4em; + margin-top: 0.4em; + margin-bottom: 0.4em; + border-style: solid; + border-bottom-width: 1px; + border-top-width: 1px; + border-right-width: 1px; + border-left-width: 1px; + border-color: #cccccc; +} + +/* We would use a div here, but it triggers a rendering bug. */ + +table.setInside { + width: 100%; + border-spacing: 0; +} + +table.setInside td.setInside { + padding: 6px; + padding-bottom: 0; +} + +/* + * Global Header + * + * This is currently a gray stripe at the top of each portal and + * application page. The left side, a context bar, uses the class + * attribute "globalNavigation" and the right uses "globalControl". + */ + +table.globalHeader { + background-color: rgb(225,225,225); + font-size: 10pt; + width: 100%; +} + +table.globalHeader td { + padding: 6px; + padding-bottom: 7px; + vertical-align: middle; +} + +table.globalHeader td.globalLogo { + width: 25px; + height: 25px; + background-image: url(RHCLogoRoundRedSmallest.png); + background-repeat: no-repeat; +} + +td.globalNavigation { + color: #3F3F3F; +} + +td.globalNavigation a { + color: #3F3F3F; +} + +td.global-links { + float: right; +} + +td.global-link-icon { + padding: 0 4px 0 10px; +} + +td.global-link-icon img { + border: 0; +} + +td.global-link a { + color: blue; + text-decoration: none; +} + +td.globalNavigation span.contextBarSeparator { + color: #3F3F3F; + font-weight: bold; +} + +td.globalNavigation span.immediateContext { + color: 3F3F3F; + font-weight: bold; +} + +form.globalSearch { + margin: 0; + border: 0; + padding: 0; +} + +td.globalControl { + color: 3F3F3F; + margin: 0; + padding: 0; + padding-right: 6px; + text-align: right; + vertical-align: middle; + font-weight: bold; +} + +td.globalControl a, +td.globalControl img { + margin: 0; + padding: 0; + color: 3F3F3F; + vertical-align: middle; + border: 0 none; + text-decoration: none; +} + +/* + * Local Header + * + * The header elements right under the blue stripe. These are + * elements logically connected to the current application, not to the + * system in general. + */ + +table.localHeader { + width: 100%; +} + +table.localHeader td.localTitle { + text-align: left; + font-weight: bold; + font-size: 12pt; +} + +table.localHeader td.localControl, +table.localHeader td.localControl a { + text-align: right; +} + +/* + * Split Panel + */ + +table.splitPanel { + width: 100%; +} + +table.splitPanelHeader { + /* Nothing here yet. */ +} + +td.splitPanelLeft { + width: 25%; +} + +td.splitPanelRight { + width: 75%; +} + +/* + * Tabs and Header/Body/Footer Separators + */ + +table.topRuleNoTabs { + background-color: rgb(162,30,30); + width: 100%; + margin: 0; + margin-bottom: 6px; + border-top: 1px solid black; + padding: 0; +} + +table.topRuleUnderTabs { + background-color: rgb(162,30,30); + width: 100%; + margin: 0; + margin-bottom: 6px; + padding: 0; +} + +table.bottomRule { + background-color: rgb(162,30,30); + width: 100%; + margin: 0; + margin-top: 6px; + border-bottom: 1px solid black; + padding: 0; +} + +table.tabs { + margin: 0; + border-spacing: 0; +} + +table.tabs a { + color: black; + text-decoration: none; + white-space: nowrap; +} + +table.tabs td { + margin: 0; + border: 0; + padding: 0; + font-weight: bold; + font-size: 10pt; + color: black; + text-decoration: none; + white-space: nowrap; +} + +table.tabs td.activeTab { + vertical-align: middle; + background-color: rgb(162,30,30); + border-top: 1px solid black; + color: #FFFFFF; + padding-top: 1px; +} + +table.tabs td.inactiveTab { + vertical-align: middle; + background-color: rgb(225,225,225); + border-top: 1px solid black; + border-bottom: 1px solid black; + color: #DDDDDD; + padding-top: 2px; +} + +table.tabs td.trimSpace { + border-bottom: 1px solid black; +} + +table.tabs td.tabBeginning { + border-left: 1px solid black; + border-top: 1px solid black; + background-color: rgb(162,30,30); + width: 6px; +} + +table.tabs td.tabBeginningOff { + border-top: 1px solid black; + border-left: 1px solid black; + border-bottom: 1px solid black; + background-color: rgb(225,225,225); + width: 6px; +} + +table.tabs td.tabEnd { + border-top: 1px solid black; + border-right: 1px solid black; + background-color: rgb(162,30,30); + width: 6px; +} + +table.tabs td.tabEndOff { + border-right: 1px solid black; + border-top: 1px solid black; + border-bottom: 1px solid black; + background-color: rgb(225,225,225); + width: 6px; +} + +/* + * Portals and Portlets + * + * "NW" denotes Narrow and Wide columns, in that order. Other layouts + * will require other CSS rules. + */ + +table.portalLayoutNW { + width: 100%; + margin: 0; + padding: 0; +} + +table.portalLayoutNW td.narrowColumn { + width: 25%; +} + +table.portalLayoutNW td.columnSeparator { + border: 0; + padding: 0; +} + +table.portalLayoutNW td.wideColumn { + width: 75%; +} + +table.portalLayoutW { + width: 100%; + margin: 0; + padding: 0; +} + +table.portalLayoutW td.VeryWideColumn { + width:100%; +} + +table.portalLayoutWN { + width: 100%; + margin: 0; + padding: 0; +} + +table.portalLayoutWN td.narrowColumn { + width: 25%; +} + +table.portalLayoutWN td.columnSeparator { + border: 0; + padding: 0; +} + +table.portalLayoutWN td.wideColumn { + width: 75%; +} + +table.portalLayoutNWN { + width: 100%; + margin: 0; + padding: 0; +} + +table.portalLayoutNWN td.narrowColumnLeft { + width: 25%; +} + +table.portalLayoutNWN td.narrowColumnRight { + width: 25%; +} + +table.portalLayoutNWN td.columnSeparator { + border: 0; + padding: 0; +} + +table.portalLayoutNWN td.wideColumn { + width: 50%; +} + +table.portalLayoutNNN { + width: 100%; + margin: 0; + padding: 0; +} + +table.portalLayoutNNN td.narrowColumnLeft { + width: 33%; +} + +table.portalLayoutNNN td.narrowColumnRight { + width: 33%; +} + +table.portalLayoutNNN td.columnSeparator { + border: 0; + padding: 0; +} + +table.portalLayoutNNN td.narrowColumnCenter { + width: 33%; +} + +table.portlet { + width: 100%; + margin: 0; + margin-bottom: 6px; + padding: 0; +} + +table.portlet td.portletHeader { + font-weight: bold; + background: #dddddd; + color: #666666; + padding: 4px; + padding-left: 6px; + vertical-align: middle; +} + +table.portlet td.portletIcon { + background: #dddddd; + padding: 4px; + text-align: right; +} + +table.portlet td.portletBody { + padding: 6px; +} + +/* + * Fancy Tables (for tabular data) + */ + +table.fancy { + width: 100%; + border-collapse: collapse; + border-spacing: 0; + border: 1px solid black; +} + +table.fancy th { + padding: 4px; + border:0 none; + font-size: 9pt; + text-align: left; +} + +table.fancy td { + padding: 4; + border: 0 none; + font-size: 9pt; +} + +table.fancy thead tr { + background-color: #eeeeee; +} + +table.fancy thead tr.subheading { + background-color: #93bee2; +} + +table.fancy thead tr.subheading td { + text-align: right; +} + +table.fancy tbody td.subDivider { + padding: 0; + background-color: #93bee2; +} + +table.fancy thead th { + font-weight: bold; + text-align: left; + white-space: nowrap; +} + +table.fancy thead th.numeric { + text-align: right; +} + +table.fancy thead th.date { + text-align: center; +} + +table.fancy thead th.icon { + text-align: center; +} + +table.fancy tbody td { + border-top: 1px solid black; +} + +table.fancy tbody td.noborder { + border-top: none; +} + +table.fancy tbody td.numeric { + text-align: right; +} + +table.fancy tbody td.date { + text-align: right; + white-space: nowrap; +} + +table.fancy tbody td.icon { + text-align: center; +} + +/* + * With is for tables that want to look standard (no lines on the inside) but + * also want to have the really thin line around the outside + */ +table.plainWithBorder { + width: 100%; + border-collapse: collapse; + border-spacing: 0; + border: 1px solid black; +} + + +/* + * Miscellaneous + */ + +select { + font-family: Arial, Helvetica, sans-serif; + font-size: 9pt; +} + +tr.rowEven { background-color: #eeeeff; } + +th { + font-family: Arial, Helvetica, sans-serif; + font-size: 10pt; + font-weight: bold; + text-align: left; + vertical-align: bottom; +} + +td.panelHeader { + padding-left: 0.4em; + padding-right: 0.4em; + padding-top: 0.1em; + padding-bottom: 0.1em; + vertical-align: middle; + text-align: left; + font-weight: bold; +} + +/* styles for section headers */ + +table.sectionHeader { + border:0 none; +} + +table.sectionHeader td { + font-weight:bold; + font-size:12pt; + border:0 none; + white-space:nowrap; +} + +table.sectionHeader td.add { + text-align:right; +} + +table.sectionHeader td.path { + text-align:right; + font-family:monospace; + font-weight:normal; + font-size:10pt; +} + +/* styles for colorpicker */ +table.colorband { + border:1px solid black; +} +table.colorband td { + width:20px; + height:20px; + border:1px solid black; +} + +/* styles for controlBar */ + +table.controlBar { + width:100%; + font-size:8pt; + border:0 none; + border-collapse:collapse; + border-spacing:0; + border:1px solid black; +} + +table.controlBar td { + font-size:8pt; + border:0 none; + white-space:nowrap; +} + +table.controlBar span { + font-size:8pt; + font-weight:bold; + border:0 none; + white-space:nowrap; +} + +table.controlBar select { + font-size:8pt; + vertical-align: middle; +} + +table.controlBar input { + font-size:8pt; + vertical-align: middle; +} + +table.controlBar img { + vertical-align: middle; +} + +tbody.controlBar td { + border-top:1px solid black; +} + +tbody.controlBar td.numeric { + text-align:right; + padding-right:20px; +} + +tbody.controlBar td.date { + text-align:right; + white-space:nowrap; +} + +tbody.controlBar td.icon { + text-align:center; +} + +/**************Admin style*****************/ + +body { + margin: 0; +} +div.tabs div, div.tabs table { + position: relative; +} + +div.tabs { + margin: 0px 0 4px 0; +} + +div.tabs table { + margin-left: 6px; +} + +div.tabs table.tab-set { + top: 1px; + border-collapse: collapse; + float: left; + margin-left: 6px; + margin: 0 0 0 4px; + border: 0; + padding: 0; + border-spacing: 0; + font-size: x-small; +} + +div.tabs table td { + margin: 0; + border: 0; + padding: 0; +} +div.tabs table td.end { + width: 10px; +} + +div.tabs table td.label { + padding: 5px 0 3px 10px; +} + +div.tabs table td.current-tab-end { + width: 10px; +} + +div.tabs table td.current-tab-label { + padding: 5px 0 3px 10px; +} + +/* When selected */ + +div.tabs table.selected { + z-index: 20; + background: rgb(162,30,30) url(tab-selected.png) no-repeat; +} + +div.tabs table.tab-set td.current-tab-label { + color: white; + background: rgb(162,30,30) url(tab-selected.png) no-repeat; +} +div.tabs table.tab-set td.current-tab-end { + background: url(tab-selected-end.png) no-repeat; +} + +/* When not selected */ + +div.tabs table.unselected { + background: rgb(225,225,225) url(tab-unselected.png) no-repeat; +} + +div.tabs table.tab-set td.label { + color: rgb(63,63,63); + background: rgb(225,225,225) url(tab-unselected.png) no-repeat; +} + +div.tabs table.tab-set td.end { + background: url(tab-unselected-end.png) no-repeat; +} + +div.tabs table.tab-set td.tab-spacer { + width: 4px; +} + +div.tabs a { + text-decoration: none; +} + +div.tabs table.rule { + width: 100%; + clear: left; + background: rgb(162,30,30) url(tab-bar.png) repeat-x; + height: 11px; + margin: 0px; + padding: 0px; +} + diff --git a/ccm-portalserver/web/packages/portalserver/www/css/tab-bar.png b/ccm-portalserver/web/packages/portalserver/www/css/tab-bar.png new file mode 100644 index 000000000..9c5ea5a1e Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/css/tab-bar.png differ diff --git a/ccm-portalserver/web/packages/portalserver/www/css/tab-selected-end.png b/ccm-portalserver/web/packages/portalserver/www/css/tab-selected-end.png new file mode 100644 index 000000000..e7890a8c2 Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/css/tab-selected-end.png differ diff --git a/ccm-portalserver/web/packages/portalserver/www/css/tab-selected.png b/ccm-portalserver/web/packages/portalserver/www/css/tab-selected.png new file mode 100644 index 000000000..19ebe5fec Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/css/tab-selected.png differ diff --git a/ccm-portalserver/web/packages/portalserver/www/css/tab-unselected-end.png b/ccm-portalserver/web/packages/portalserver/www/css/tab-unselected-end.png new file mode 100644 index 000000000..de7b61aa6 Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/css/tab-unselected-end.png differ diff --git a/ccm-portalserver/web/packages/portalserver/www/css/tab-unselected.png b/ccm-portalserver/web/packages/portalserver/www/css/tab-unselected.png new file mode 100644 index 000000000..e6a6b9f4b Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/css/tab-unselected.png differ diff --git a/ccm-portalserver/web/packages/portalserver/www/misc/assets/ufp.jpg b/ccm-portalserver/web/packages/portalserver/www/misc/assets/ufp.jpg new file mode 100644 index 000000000..87c767a1b Binary files /dev/null and b/ccm-portalserver/web/packages/portalserver/www/misc/assets/ufp.jpg differ diff --git a/ccm-portalserver/web/packages/portalserver/xsl/portal-sitemap.xsl b/ccm-portalserver/web/packages/portalserver/xsl/portal-sitemap.xsl new file mode 100644 index 000000000..2f46855ff --- /dev/null +++ b/ccm-portalserver/web/packages/portalserver/xsl/portal-sitemap.xsl @@ -0,0 +1,395 @@ + + + + + + + + + + + +/packages/portalserver/www/assets/packages/portalserver/www/css + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    + + + +
    + + + +
    + + + +
    + + + +
    +
    + + +
    + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + + + + + + + + + + + + + + + + +
    + + + +
    + + + +
    +
    + + + + + +
    + + + +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/ccm-portalserver/web/packages/portalserver/xsl/portalserver.xsl b/ccm-portalserver/web/packages/portalserver/xsl/portalserver.xsl new file mode 100644 index 000000000..bc5d14e2a --- /dev/null +++ b/ccm-portalserver/web/packages/portalserver/xsl/portalserver.xsl @@ -0,0 +1,1060 @@ + + + + + + + + + + + + + + + + + + +/packages/portalserver/www/assets +/packages/portalserver/www/css + + + + + <xsl:value-of select="bebop:title"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + <xsl:value-of select="bebop:title"/> + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    + + + +
    +
    + + + + + + + + + + + + + + + + + +
    + + + + +
    +
    + + +
    + + + + + + +
    + + + + +
    + +
    +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
           + + + + + + + +
        
    +
      
    + + + +
    +
    + + + +
    +
    +
    + + + + +
    + + + +
    + +
    + + + + + + + &nbsp;&gt;&nbsp; + + + + + + + + + + + + + + + + + + + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    + + + + + + + + + + + + + + +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
           + + + + + + + +
       +   
    +
      
    + + + +
    + + +
    + + +
    + + + + + + + + +
    + + + + + + + +
    +
    + +
    +
    + + + + +

    This tab does not have any portlets yet.

    +
    + + + + + + + +
    + + + + + + + +
    +
    +
    +
    + + + + +

    This tab does not have any portlets yet.

    +
    + + + + + +
    + +
    +
    +
    +
    + + + + +

    This tab does not have any portlets yet.

    +
    + + + + + + + +
    + + + + + + + +
    +
    +
    +
    + + + + +

    This tab does not have any portlets yet.

    +
    + + + + + + + +
    + + + + + + + +
    +
    +
    +
    + + + + +

    This tab does not have any portlets yet.

    +
    + + + + + + + + + +
    + + + + + + + + + + + +
    +
    +
    +
    + + + + +

    This tab does not have any portlets yet.

    +
    + + + + + + + + + +
    + + + + + + + + + + + +
    +
    +
    +
    + + + + + + + + + + +
    + + + + Move Portlet left + + + + Move Portlet Up + + + + Move Portlet Down + + + + Move Portlet right + + + + Customize Portlet + + + Remove Portlet + + + + + + Zoom In + + + + + + + + + +
    + +
    +
    + + + + + + + + + + + + + + + + +
    :
    + Actions: +
    +
    + + + + + + +
    View and Manage
    + + + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    DescriptionConfigure Tool  PortletsConfigure Portlet
    + +
    + + + +   + + + +   + 1. None 
    .
    +
    + + +
    + + + + + +
    + + + + + + + +
    + +   + +
    + This Workspace + Entire System +
    +
    Advanced Search
    +
    +
    + + + + + + + + + /assets/download.gif + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + + + + + + + +
    +
    + + +
      +
    • Group Name:
    • +
    • Primary Email:
    • +
    +
    + + + + + + + + + + + + + + + + + +
    Application Link
    + +
    +
    + + + + + + + + + + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + +   + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    Portal NameCreation Date
    +
    +
    + + +
    + + + + + + + + + + + + + + + + + + + +
    Portal NameArchive Date
    +
    +
    + +
    diff --git a/ccm-portalserver/web/packages/portalserver/xsl/simple-page.xsl b/ccm-portalserver/web/packages/portalserver/xsl/simple-page.xsl new file mode 100644 index 000000000..7837e35a3 --- /dev/null +++ b/ccm-portalserver/web/packages/portalserver/xsl/simple-page.xsl @@ -0,0 +1,132 @@ + + + + + + + + + + + <xsl:value-of select="bebop:title"/> + + + + + + + +
    + +
    + + + + + + +
    + + + + +
    +
    + + + + + +
    + + + + +
    +
    + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + +
    +
    + + + + + + + +
    + + + + + +
    + + + + + +
    + + + + +
    +
    + + + + + +
    + + + + +
    +
    + + + + + +
    + +
    + + + + +
    + + + + + + + + + +
    diff --git a/ccm-portalserver/web/packages/portalserver/xsl/ui.xsl b/ccm-portalserver/web/packages/portalserver/xsl/ui.xsl new file mode 100644 index 000000000..b6a4258fe --- /dev/null +++ b/ccm-portalserver/web/packages/portalserver/xsl/ui.xsl @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + +
           + + + + +
    + +   + +   + + +
    +
    + + + + + + + + + + +
    +
    +
    + + + + + + + + + +
           + + + + +
    + You are not currently logged in +
    +
    + + + + + Login + +
    +
    +
    +
    + +
    + diff --git a/ccm-portalserver/web/packages/portlets/xsl/content-directory-portlet.xsl b/ccm-portalserver/web/packages/portlets/xsl/content-directory-portlet.xsl new file mode 100644 index 000000000..3a29adf65 --- /dev/null +++ b/ccm-portalserver/web/packages/portlets/xsl/content-directory-portlet.xsl @@ -0,0 +1,40 @@ + + + + + + + + + + + +
    + + + + | + + +
    +
    + + + + + + + <tr> + + + + </tr> + + +
    + +
    +
    + +
    diff --git a/ccm-portalserver/web/packages/portlets/xsl/content-item-portlet.xsl b/ccm-portalserver/web/packages/portlets/xsl/content-item-portlet.xsl new file mode 100644 index 000000000..f26743f41 --- /dev/null +++ b/ccm-portalserver/web/packages/portlets/xsl/content-item-portlet.xsl @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/ccm-portalserver/web/packages/portlets/xsl/content-sections-portlet.xsl b/ccm-portalserver/web/packages/portlets/xsl/content-sections-portlet.xsl new file mode 100644 index 000000000..2af26a78d --- /dev/null +++ b/ccm-portalserver/web/packages/portlets/xsl/content-sections-portlet.xsl @@ -0,0 +1,36 @@ + + + + + + + + + + + + + admin + + admin + + + + + + + + + + table_row_odd + table_row_even + + + + + +
    +
    + +
    diff --git a/ccm-portalserver/web/packages/portlets/xsl/freeform-html-portlet.xsl b/ccm-portalserver/web/packages/portlets/xsl/freeform-html-portlet.xsl new file mode 100644 index 000000000..0d4b4aed4 --- /dev/null +++ b/ccm-portalserver/web/packages/portlets/xsl/freeform-html-portlet.xsl @@ -0,0 +1,12 @@ + + + + + +
    + +
    +
    + +
    diff --git a/ccm-portalserver/web/packages/portlets/xsl/rss-feed-portlet.xsl b/ccm-portalserver/web/packages/portlets/xsl/rss-feed-portlet.xsl new file mode 100644 index 000000000..de30de214 --- /dev/null +++ b/ccm-portalserver/web/packages/portlets/xsl/rss-feed-portlet.xsl @@ -0,0 +1,79 @@ + + + + + + + + + + + + +
    + +
    +
    + + + + + + + + + + + + +
    + +
    +
    +
    + + + + + +
    + +
    +
    +
    + + +
    + +
    +
    + +
    +
    + + + + + + +
    + +
    +
    +
    + + +
    + +
    +
    + +
    +
    + +
    diff --git a/ccm-portalserver/web/packages/portlets/xsl/tasklist-portlet.xsl b/ccm-portalserver/web/packages/portlets/xsl/tasklist-portlet.xsl new file mode 100644 index 000000000..139db2667 --- /dev/null +++ b/ccm-portalserver/web/packages/portlets/xsl/tasklist-portlet.xsl @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + , + + No assigned users + + + 1 assigned user + + + assigned users + + + + + + +

    No tasks to display.

    +
    + + + + + + + + table_row_odd + table_row_even + + + + + +
    Item TitleActionDue DateStatus
    +
    +
    + +
    diff --git a/ccm-portalserver/web/packages/portlets/xsl/time-of-day-portlet.xsl b/ccm-portalserver/web/packages/portlets/xsl/time-of-day-portlet.xsl new file mode 100644 index 000000000..a7148b71d --- /dev/null +++ b/ccm-portalserver/web/packages/portlets/xsl/time-of-day-portlet.xsl @@ -0,0 +1,11 @@ + + + + + + + + + +