From: <udi...@us...> - 2022-02-16 13:52:38
|
Revision: 1438 http://sourceforge.net/p/j-trac/code/1438 Author: udittmer Date: 2022-02-16 13:52:35 +0000 (Wed, 16 Feb 2022) Log Message: ----------- #176: Spaces can be made inactive Modified Paths: -------------- trunk/jtrac/src/main/java/info/jtrac/domain/Space.java trunk/jtrac/src/main/java/info/jtrac/domain/UserSpaceRole.java trunk/jtrac/src/main/java/info/jtrac/wicket/DashboardPage.java trunk/jtrac/src/main/java/info/jtrac/wicket/SpaceFormPage.html trunk/jtrac/src/main/java/info/jtrac/wicket/SpaceFormPage.java trunk/jtrac/src/main/resources/jtrac.hbm.xml trunk/jtrac/src/main/resources/messages.properties trunk/jtrac/src/main/resources/messages_de.properties trunk/jtrac/src/main/resources/messages_en.properties Modified: trunk/jtrac/src/main/java/info/jtrac/domain/Space.java =================================================================== --- trunk/jtrac/src/main/java/info/jtrac/domain/Space.java 2022-02-16 10:55:50 UTC (rev 1437) +++ trunk/jtrac/src/main/java/info/jtrac/domain/Space.java 2022-02-16 13:52:35 UTC (rev 1438) @@ -1,12 +1,12 @@ /* * Copyright 2002-2005 the original author or authors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -27,7 +27,7 @@ * space with different access permissions. */ public class Space implements Serializable, Comparable<Space> { - + private long id; private int version; private Integer type; @@ -34,15 +34,16 @@ private String prefixCode; private String name; private String description; - private boolean guestAllowed; + private boolean guestAllowed; + private boolean isActive = true; private Metadata metadata; - + public Space() { metadata = new Metadata(); } - + //======================================================= - + public int getVersion() { return version; } @@ -49,8 +50,8 @@ public void setVersion(int version) { this.version = version; - } - + } + public String getPrefixCode() { return prefixCode; } @@ -65,8 +66,8 @@ public void setName(String name) { this.name = name; - } - + } + public String getDescription() { return description; } @@ -97,16 +98,24 @@ public void setType(Integer type) { this.type = type; - } - + } + public boolean isGuestAllowed() { return guestAllowed; } - public void setGuestAllowed(boolean guestAllowed) { + public void setGuestAllowed (boolean guestAllowed) { this.guestAllowed = guestAllowed; - } - + } + + public boolean getIsActive() { + return isActive; + } + + public void setIsActive (boolean isActive) { + this.isActive = isActive; + } + @Override public String toString() { StringBuffer sb = new StringBuffer(); @@ -115,7 +124,7 @@ sb.append("]"); return sb.toString(); } - + public int compareTo(Space s) { if(s == null) { return 1; @@ -124,7 +133,7 @@ if(name == null) { return 0; } - return 1; + return 1; } if(name == null) { return -1; @@ -131,8 +140,8 @@ } return name.compareTo(s.name); } - - + + @Override public boolean equals(Object o) { if (this == o) { @@ -144,10 +153,10 @@ final Space s = (Space) o; return prefixCode.equals(s.getPrefixCode()); } - + @Override public int hashCode() { return prefixCode.hashCode(); } - + } Modified: trunk/jtrac/src/main/java/info/jtrac/domain/UserSpaceRole.java =================================================================== --- trunk/jtrac/src/main/java/info/jtrac/domain/UserSpaceRole.java 2022-02-16 10:55:50 UTC (rev 1437) +++ trunk/jtrac/src/main/java/info/jtrac/domain/UserSpaceRole.java 2022-02-16 13:52:35 UTC (rev 1438) @@ -1,144 +1,144 @@ -/* - * Copyright 2002-2005 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package info.jtrac.domain; - -import java.io.Serializable; -import org.acegisecurity.GrantedAuthority; - -/** - * Class that exists purely to hold a "ternary" mapping of - * user <--> space <--> role and is also persisted - * the JTrac authorization (access control) scheme works as follows: - * if space is null, that means that this is a "global" JTrac role - * if space is not null, this role applies for the user to that - * space, and the getAuthority() method used by Acegi returns the - * role key appended with ":" + spacePrefixCode - */ -public class UserSpaceRole implements GrantedAuthority, Serializable { - - private long id; - private User user; - private Space space; - private String roleKey; - - public UserSpaceRole() { - // zero arg constructor - } - - public UserSpaceRole(User user, Space space, String roleKey) { - this.user = user; - this.space = space; - this.roleKey = roleKey; - } - - public boolean isAbleToCreateNewItem() { - if (space == null) { - return false; - } - return user.getPermittedTransitions(space, State.NEW).size() > 0; - } - - public boolean isSuperUser() { - return space == null && isAdmin(); - } - - public boolean isSpaceAdmin() { - return space != null && isAdmin(); - } - - public boolean isAdmin() { - return Role.ROLE_ADMIN.equals(roleKey); - } - - public boolean isGuest() { - return Role.ROLE_GUEST.equals(roleKey); - } - - //======== ACEGI GrantedAuthority implementation ============= - - public String getAuthority() { - if (space != null) { - return roleKey + ":" + space.getPrefixCode(); - } - return roleKey; - } - - //============================================================= - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public String getRoleKey() { - return roleKey; - } - - public void setRoleKey(String roleKey) { - this.roleKey = roleKey; - } - - public Space getSpace() { - return space; - } - - public void setSpace(Space space) { - this.space = space; - } - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof UserSpaceRole)) { - return false; - } - final UserSpaceRole usr = (UserSpaceRole) o; - return ( - (space == usr.getSpace() || space.equals(usr.getSpace())) - && user.equals(usr.getUser()) - && roleKey.equals(usr.getRoleKey()) - ); - } - - @Override - public int hashCode() { - int hash = 7; - hash = hash * 31 + user.hashCode(); - hash = hash * 31 + (space == null ? 0 : space.hashCode()); - hash = hash * 31 + roleKey.hashCode(); - return hash; - } - - @Override - public String toString() { - return getAuthority(); - } - -} +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package info.jtrac.domain; + +import java.io.Serializable; +import org.acegisecurity.GrantedAuthority; + +/** + * Class that exists purely to hold a "ternary" mapping of + * user <--> space <--> role and is also persisted + * the JTrac authorization (access control) scheme works as follows: + * if space is null, that means that this is a "global" JTrac role + * if space is not null, this role applies for the user to that + * space, and the getAuthority() method used by Acegi returns the + * role key appended with ":" + spacePrefixCode + */ +public class UserSpaceRole implements GrantedAuthority, Serializable { + + private long id; + private User user; + private Space space; + private String roleKey; + + public UserSpaceRole() { + // zero arg constructor + } + + public UserSpaceRole(User user, Space space, String roleKey) { + this.user = user; + this.space = space; + this.roleKey = roleKey; + } + + public boolean isAbleToCreateNewItem() { + if (space == null) { + return false; + } + return user.getPermittedTransitions(space, State.NEW).size() > 0; + } + + public boolean isSuperUser() { + return space == null && isAdmin(); + } + + public boolean isSpaceAdmin() { + return space != null && isAdmin(); + } + + public boolean isAdmin() { + return Role.ROLE_ADMIN.equals(roleKey); + } + + public boolean isGuest() { + return Role.ROLE_GUEST.equals(roleKey); + } + + //======== ACEGI GrantedAuthority implementation ============= + + public String getAuthority() { + if (space != null) { + return roleKey + ":" + space.getPrefixCode(); + } + return roleKey; + } + + //============================================================= + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public String getRoleKey() { + return roleKey; + } + + public void setRoleKey(String roleKey) { + this.roleKey = roleKey; + } + + public Space getSpace() { + return space; + } + + public void setSpace(Space space) { + this.space = space; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof UserSpaceRole)) { + return false; + } + final UserSpaceRole usr = (UserSpaceRole) o; + return ( + (space == usr.getSpace() || space.equals(usr.getSpace())) + && user.equals(usr.getUser()) + && roleKey.equals(usr.getRoleKey()) + ); + } + + @Override + public int hashCode() { + int hash = 7; + hash = hash * 31 + user.hashCode(); + hash = hash * 31 + (space == null ? 0 : space.hashCode()); + hash = hash * 31 + roleKey.hashCode(); + return hash; + } + + @Override + public String toString() { + return getAuthority(); + } + +} Modified: trunk/jtrac/src/main/java/info/jtrac/wicket/DashboardPage.java =================================================================== --- trunk/jtrac/src/main/java/info/jtrac/wicket/DashboardPage.java 2022-02-16 10:55:50 UTC (rev 1437) +++ trunk/jtrac/src/main/java/info/jtrac/wicket/DashboardPage.java 2022-02-16 13:52:35 UTC (rev 1438) @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import org.apache.wicket.behavior.SimpleAttributeModifier; import org.apache.wicket.markup.html.WebMarkupContainer; @@ -52,6 +53,11 @@ add(table); add(message); + // remove spaces that are not active + spaceRoles = spaceRoles.stream() + .filter(spaceRole -> spaceRole.getSpace().getIsActive()) + .collect(Collectors.toList()); + if(spaceRoles.size() > 0) { final CountsHolder countsHolder = getJtrac().loadCountsForUser(user); Modified: trunk/jtrac/src/main/java/info/jtrac/wicket/SpaceFormPage.html =================================================================== --- trunk/jtrac/src/main/java/info/jtrac/wicket/SpaceFormPage.html 2022-02-16 10:55:50 UTC (rev 1437) +++ trunk/jtrac/src/main/java/info/jtrac/wicket/SpaceFormPage.html 2022-02-16 13:52:35 UTC (rev 1438) @@ -1,10 +1,10 @@ <html> <body> <wicket:extend> - <form wicket:id="form"> + <form wicket:id="form"> <div class="heading"> <wicket:message key="space_form.spaceDetails"/> - <input type="submit" wicket:id="delete" wicket:message="value:delete"/> + <input type="submit" wicket:id="delete" wicket:message="value:delete"/> </div> <div wicket:id="feedback"></div> <table class="jtrac"> @@ -12,36 +12,44 @@ <td class="label"> <wicket:message key="space_form.displayName"/> <font color="red">*</font> - </td> + </td> <td> - <input wicket:id="space.name"/> - </td> + <input wicket:id="space.name"/> + </td> </tr> <tr> <td class="label"> <wicket:message key="space_form.spaceKey"/> <font color="red">*</font> - </td> + </td> <td> - <input wicket:id="space.prefixCode" size="10"/> - </td> + <input wicket:id="space.prefixCode" size="10"/> + </td> </tr> <tr> <td class="label"> - <wicket:message key="space_form.description"/> - </td> + <wicket:message key="space_form.description"/> + </td> <td> - <textarea wicket:id="space.description" rows="3" cols="40"></textarea> - </td> + <textarea wicket:id="space.description" rows="3" cols="40"></textarea> + </td> </tr> <tr> <td class="label"> - <wicket:message key="space_form.makePublic"/> - </td> + <wicket:message key="space_form.makePublic"/> + </td> <td> - <input type="checkbox" wicket:id="space.guestAllowed"/> - </td> - </tr> + <input type="checkbox" wicket:id="space.guestAllowed"/> + </td> + </tr> + <tr> + <td class="label"> + <wicket:message key="space_form.isActive"/> + </td> + <td> + <input type="checkbox" wicket:id="space.isActive"/> + </td> + </tr> <tr wicket:id="hide"> <td class="label"> <wicket:message key="space_form.copyExisting"/> @@ -53,9 +61,9 @@ <tr> <td/> <td> - <input type="submit" wicket:message="value:next"/> + <input type="submit" wicket:message="value:next"/> </td> - </tr> + </tr> </table> <a href="#" wicket:id="cancel"><img src="resources/cancel.gif" class="nav-link"/><wicket:message key="cancel"/></a> </form> Modified: trunk/jtrac/src/main/java/info/jtrac/wicket/SpaceFormPage.java =================================================================== --- trunk/jtrac/src/main/java/info/jtrac/wicket/SpaceFormPage.java 2022-02-16 10:55:50 UTC (rev 1437) +++ trunk/jtrac/src/main/java/info/jtrac/wicket/SpaceFormPage.java 2022-02-16 13:52:35 UTC (rev 1438) @@ -193,6 +193,8 @@ add(new TextArea("space.description")); // guest allowed =================================================== add(new CheckBox("space.guestAllowed")); + // whether the space is active ===================================== + add(new CheckBox("space.isActive")); // hide copy from option if edit =================================== WebMarkupContainer hide = new WebMarkupContainer("hide"); if(space.getId() > 0) { Modified: trunk/jtrac/src/main/resources/jtrac.hbm.xml =================================================================== --- trunk/jtrac/src/main/resources/jtrac.hbm.xml 2022-02-16 10:55:50 UTC (rev 1437) +++ trunk/jtrac/src/main/resources/jtrac.hbm.xml 2022-02-16 13:52:35 UTC (rev 1438) @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE hibernate-mapping PUBLIC - "-//Hibernate/Hibernate Mapping DTD//EN" +<!DOCTYPE hibernate-mapping PUBLIC + "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="info.jtrac.domain"> @@ -12,7 +12,7 @@ <natural-id> <many-to-one name="space" column="space_id" not-null="true" index="idx_items_space_id"/> <property name="sequenceNum" column="sequence_num" index="idx_items_sequence_num"/> - </natural-id> + </natural-id> <version name="version" column="version"/> <property name="type" column="type"/> <many-to-one name="parent" column="parent_id"/> @@ -21,11 +21,11 @@ <set name="children" order-by="id" cascade="all" inverse="true"> <key column="parent_id"/> <one-to-many class="Item"/> - </set> + </set> <set name="history" order-by="id" cascade="all" inverse="true"> <key column="item_id"/> <one-to-many class="History"/> - </set> + </set> <set name="itemUsers" cascade="all"> <key column="item_id"/> <one-to-many class="ItemUser"/> @@ -37,26 +37,26 @@ <set name="relatingItems" inverse="true"> <key column="related_item_id"/> <one-to-many class="ItemItem"/> - </set> + </set> <set name="itemTags" cascade="all" inverse="true"> <key column="item_id"/> <one-to-many class="ItemTag"/> - </set> + </set> <set name="attachments" cascade="all" inverse="true"> <key column="item_id"/> <one-to-many class="Attachment"/> - </set> + </set> <!-- identical to History (except indexes) --> <many-to-one name="loggedBy" column="logged_by" not-null="true" index="idx_items_logged_by"/> - <many-to-one name="assignedTo" column="assigned_to" index="idx_items_assigned_to"/> - <property name="summary" column="summary"/> + <many-to-one name="assignedTo" column="assigned_to" index="idx_items_assigned_to"/> + <property name="summary" column="summary"/> <property name="detail" column="detail" type="text"/> <property name="status" column="status" index="idx_items_status"/> <property name="severity" column="severity" index="idx_items_severity"/> - <property name="priority" column="priority"/> + <property name="priority" column="priority"/> <property name="cusDbl01" column="cus_dbl_01"/> <property name="cusDbl02" column="cus_dbl_02"/> - <property name="cusDbl03" column="cus_dbl_03"/> + <property name="cusDbl03" column="cus_dbl_03"/> <property name="cusInt01" column="cus_int_01"/> <property name="cusInt02" column="cus_int_02"/> <property name="cusInt03" column="cus_int_03"/> @@ -74,7 +74,7 @@ <property name="cusStr05" column="cus_str_05"/> <property name="cusTim01" column="cus_tim_01"/> <property name="cusTim02" column="cus_tim_02"/> - <property name="cusTim03" column="cus_tim_03"/> + <property name="cusTim03" column="cus_tim_03"/> </class> <class name="ItemUser" table="item_users"> @@ -83,7 +83,7 @@ </id> <many-to-one name="user" column="user_id" not-null="true"/> <property name="type" column="type"/> - </class> + </class> <class name="ItemItem" table="item_items"> <id name="id" column="id"> @@ -92,8 +92,8 @@ <many-to-one name="item" column="item_id" not-null="true"/> <many-to-one name="relatedItem" column="related_item_id" not-null="true"/> <property name="type" column="type"/> - </class> - + </class> + <class name="ItemTag" table="item_tags"> <id name="id" column="id"> <generator class="native"/> @@ -100,8 +100,8 @@ </id> <many-to-one name="tag" column="tag_id" not-null="true"/> <property name="type" column="type"/> - </class> - + </class> + <class name="Tag" table="tags"> <id name="id" column="id"> <generator class="native"/> @@ -108,9 +108,9 @@ </id> <property name="type" column="type"/> <property name="name" column="name" not-null="true" unique="true"/> - <property name="description" column="description" type="text"/> + <property name="description" column="description" type="text"/> </class> - + <class name="History" table="history"> <id name="id" column="id"> <generator class="native"/> @@ -124,15 +124,15 @@ <!-- identical to Item --> <property name="timeStamp" column="time_stamp"/> <many-to-one name="loggedBy" column="logged_by" not-null="true"/> - <many-to-one name="assignedTo" column="assigned_to"/> - <property name="summary" column="summary"/> + <many-to-one name="assignedTo" column="assigned_to"/> + <property name="summary" column="summary"/> <property name="detail" column="detail" type="text"/> <property name="status" column="status"/> <property name="severity" column="severity"/> - <property name="priority" column="priority"/> + <property name="priority" column="priority"/> <property name="cusDbl01" column="cus_dbl_01"/> <property name="cusDbl02" column="cus_dbl_02"/> - <property name="cusDbl03" column="cus_dbl_03"/> + <property name="cusDbl03" column="cus_dbl_03"/> <property name="cusInt01" column="cus_int_01"/> <property name="cusInt02" column="cus_int_02"/> <property name="cusInt03" column="cus_int_03"/> @@ -150,14 +150,14 @@ <property name="cusStr05" column="cus_str_05"/> <property name="cusTim01" column="cus_tim_01"/> <property name="cusTim02" column="cus_tim_02"/> - <property name="cusTim03" column="cus_tim_03"/> - </class> - + <property name="cusTim03" column="cus_tim_03"/> + </class> + <class name="User" table="users"> <id name="id" column="id"> <generator class="native"/> - </id> - <property name="type" column="type"/> + </id> + <property name="type" column="type"/> <many-to-one name="parent" column="parent"/> <property name="loginName" column="login_name" unique="true" not-null="true" index="idx_users_login_name" length="50"/> <property name="name" column="name" length="50"/> @@ -169,7 +169,7 @@ <set name="userSpaceRoles" cascade="all" inverse="true"> <key column="user_id"/> <one-to-many class="UserSpaceRole"/> - </set> + </set> </class> <class name="UserSpaceRole" table="user_space_roles"> @@ -179,8 +179,8 @@ <many-to-one name="user" column="user_id"/> <many-to-one name="space" column="space_id"/> <property name="roleKey" column="role_key" not-null="true"/> - </class> - + </class> + <class name="Space" table="spaces"> <id name="id" column="id"> <generator class="native"/> @@ -190,29 +190,30 @@ <property name="prefixCode" column="prefix_code" unique="true" length="10"/> <property name="name" column="name" length="50"/> <property name="description" column="description" type="text"/> - <property name="guestAllowed" column="guest_allowed"/> - <many-to-one name="metadata" column="metadata_id" cascade="all"/> + <property name="guestAllowed" column="guest_allowed"/> + <property name="isActive" column="is_active" type="boolean"/> + <many-to-one name="metadata" column="metadata_id" cascade="all"/> </class> - + <class name="SpaceSequence" table="space_sequence"> <id name="id" column="id"> - <generator class="assigned"/> - </id> - <property name="nextSeqNum" column="next_seq_num"/> + <generator class="assigned"/> + </id> + <property name="nextSeqNum" column="next_seq_num"/> </class> - + <class name="Metadata" table="metadata"> <id name="id" column="id"> <generator class="native"/> </id> <version name="version" column="version"/> - <property name="type" column="type"/> + <property name="type" column="type"/> <property name="name" column="name" length="50"/> <property name="description" column="description" type="text"/> <many-to-one name="parent" column="parent_id"/> <property name="xmlString" column="xml_string" type="text"/> - </class> - + </class> + <class name="Attachment" table="attachments"> <id name="id" column="id"> <generator class="native"/> @@ -220,12 +221,12 @@ <many-to-one name="previous" column="previous_id"/> <property name="fileName" column="file_name"/> <property name="filePrefix" column="file_prefix"/> - </class> - + </class> + <class name="Config" table="config"> - <id name="param" column="param"/> + <id name="param" column="param"/> <property name="value" column="value"/> - </class> + </class> <class name="StoredSearch" table="storedsearch"> <id name="id" column="id"> Modified: trunk/jtrac/src/main/resources/messages.properties =================================================================== --- trunk/jtrac/src/main/resources/messages.properties 2022-02-16 10:55:50 UTC (rev 1437) +++ trunk/jtrac/src/main/resources/messages.properties 2022-02-16 13:52:35 UTC (rev 1438) @@ -345,6 +345,7 @@ space_form.description = Description space_form.makePublic = Make Public space_form.allowGuest = Allow Guest (read only) Access +space_form.isActive = Space is active space_form.copyExisting = Copy Existing Space space_form.createFresh = create from scratch space_form.error.prefixCode.tooShort = Length should be at least 3 characters. Modified: trunk/jtrac/src/main/resources/messages_de.properties =================================================================== --- trunk/jtrac/src/main/resources/messages_de.properties 2022-02-16 10:55:50 UTC (rev 1437) +++ trunk/jtrac/src/main/resources/messages_de.properties 2022-02-16 13:52:35 UTC (rev 1438) @@ -343,7 +343,8 @@ space_form.spaceKey = Kurzname space_form.description = Beschreibung space_form.makePublic = \u00D6ffentliches Projekt -space_form.allowGuest = Gast-zugriff erlauben (nur lesen) +space_form.allowGuest = Gast-Zugriff erlauben (nur lesen) +space_form.isActive = Projekt ist aktiv space_form.copyExisting = Bestehendes Projekt kopieren space_form.createFresh = Leeres Projekt erstellen space_form.error.prefixCode.tooShort = L\u00E4nge mindestens 3 Zeichen. Modified: trunk/jtrac/src/main/resources/messages_en.properties =================================================================== --- trunk/jtrac/src/main/resources/messages_en.properties 2022-02-16 10:55:50 UTC (rev 1437) +++ trunk/jtrac/src/main/resources/messages_en.properties 2022-02-16 13:52:35 UTC (rev 1438) @@ -345,6 +345,7 @@ space_form.description = Description space_form.makePublic = Make Public space_form.allowGuest = Allow Guest (read only) Access +space_form.isActive = Space is active space_form.copyExisting = Copy Existing Space space_form.createFresh = create from scratch space_form.error.prefixCode.tooShort = Length should be at least 3 characters. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |