Project import generated by Copybara.
GitOrigin-RevId: d9e9e3fb4e31372ec1fb43b178994ca78fa8fe70
diff --git a/templates/project/people-add-members-form.ezt b/templates/project/people-add-members-form.ezt
new file mode 100644
index 0000000..f013a0a
--- /dev/null
+++ b/templates/project/people-add-members-form.ezt
@@ -0,0 +1,103 @@
+
+[if-any offer_membership_editing]
+<br>
+<div class="h4" style="margin-bottom:4px" id="addmembers">Add Members</div>
+
+<div id="makechanges" class="closed">
+
+ <div class="ifClosed">
+ <textarea id="tempt" rows="4" style="color:#666; width:500px; margin-left:4px"
+ >Enter new member email addresses</textarea>
+ </div>
+
+
+<table class="ifOpened vt" cellspacing="2" cellpadding="2" style="margin-top:0">
+ <tr>
+ <td colspan="2">
+ <textarea name="addmembers" style="width:500px" rows="4"
+ id="addMembersTextArea">[initial_add_members]</textarea>
+ [if-any errors.addmembers]
+ <div class="fielderror">[errors.addmembers]</div>
+ [end]<br>
+ </td>
+ <td rowspan="3">
+ <div class="tip" style="margin-top:0; margin-left:4px">
+ Enter the email addresses of users that you would like to
+ add to this [is arg0 "project"]project[else]
+ [is arg0 "hotlist"]hotlist.
+ <strong>You can also add group lists to give every member of the group permission to edit this hotlist</strong>
+ [else]group[end][end].<br><br>
+ Each email address must correspond to a Google Account when in use.
+ </div>
+ </td>
+ </tr>
+
+ <tr>
+ <th width="30" align="left">Role:</th>
+
+ <td width="470" align="left">
+ [is arg0 "project"]
+ <input type="radio" name="role" value="owner" id="owner">
+ <label for="owner">Owner: may make any change to this
+ project.</label><br>
+
+ <input type="radio" name="role" value="committer" id="committer"
+ checked="checked">
+ <label for="committer">Committer: may work in the project, but may
+ not reconfigure it.</label><br>
+
+ <input type="radio" name="role" value="contributor" id="contributor">
+ <label for="contributor">Contributor: starts with the same permissions
+ as non-members.</label><br>
+ [# TODO(jrobbins): custom roles]
+ [else][is arg0 "hotlist"]
+ <input type="radio" name="role" value="editor" id="editor"
+ checked="checked">
+ <label for="editor">Editor: may add/remove/rank issues.</label><br>
+ [if-any errors.incorrect_email_input]
+ <div class="fielderror">[errors.incorrect_email_input]</div>
+ [end]
+ [else]
+ <input type="radio" name="role" value="owner" id="owner">
+ <label for="owner">Owner: may make any change to this
+ group.</label><br>
+
+ <input type="radio" name="role" value="member" id="member"
+ checked="checked">
+ <label for="member">Member: member of this user group.</label><br>
+ [end][end]
+ </td>
+
+ </tr>
+ <tr>
+ <td colspan="2">
+ <input type="submit" name="addbtn" id="addbtn"
+ value="Save changes" style="margin-top:1em">
+ </td>
+ </tr>
+</table>
+
+</div>
+
+
+<script type="text/javascript" nonce="[nonce]">
+runOnLoad(function() {
+ window._openAddMembersForm = function _openAddMembersForm() {
+ document.location.hash='addmembers';
+ document.getElementById('makechanges').className = "opened";
+ window.setTimeout(
+ function () { document.getElementById('addMembersTextArea').focus(); },
+ 100);
+ }
+
+ [if-any initially_expand_form]
+ _openAddMembersForm();
+ [end]
+
+ if ($("tempt"))
+ $("tempt").addEventListener("mousedown", _openAddMembersForm);
+
+});
+</script>
+
+[end]
diff --git a/templates/project/people-detail-page.ezt b/templates/project/people-detail-page.ezt
new file mode 100644
index 0000000..fda3e96
--- /dev/null
+++ b/templates/project/people-detail-page.ezt
@@ -0,0 +1,186 @@
+[define category_css]css/ph_detail.css[end]
+[include "../framework/header.ezt" "showtabs"]
+
+<a href="list">‹ Back to people list</a>
+
+<form action="detail.do" method="POST" id="peopledetail">
+<input type="hidden" name="token" value="[form_token]">
+<input type="hidden" name="u" value="[member.user.user_id]">
+<table cellspacing="8" class="rowmajor vt">
+<tr>
+ <th width="1%">User:</th>
+ <td>[include "../framework/user-link.ezt" member.user]</td>
+</tr>
+
+ <tr class="[if-any expand_perms]opened[else]closed[end]">
+ <th>Role:</th>
+ <td>
+ [# Show a widget if the current user is allowed to edit roles.]
+ [if-any perms.EditProject]
+ [define offer_role_select]Yes[end]
+ [else]
+ [define offer_role_select]No[end]
+ [end]
+ [# But, don't offer it if the user could remove themselves as the last owner.]
+ [is total_num_owners "1"][if-any warn_abandonment]
+ [define offer_role_select]No[end]
+ [end][end]
+
+ [is offer_role_select "Yes"]
+ <select name="role">
+ <option [is member.role "Owner"]selected="selected"[end]
+ value="owner">Owner</option>
+ <option [is member.role "Committer"]selected="selected"[end]
+ value="committer">Committer</option>
+ <option [is member.role "Contributor"]selected="selected"[end]
+ value="contributor">Contributor</option>
+ </select>
+ [else]
+ [member.role]
+ [end]
+ <a class="ifClosed toggleHidden" href="#" id="show_permissions"
+ style="font-size:90%; margin-left:1em">Show permissions</a>
+ <a class="ifOpened toggleHidden" href="#" id="hide_permissions"
+ style="font-size:90%; margin-left:1em">Hide permissions</a>
+ [include "people-detail-perms-part.ezt"]
+ </td>
+ <td>
+ <div class="ifOpened tip" style="width:17em">
+ <b>Permissions</b> enable members to perform specific actions in
+ a project. Appropriate permissions are already defined for each
+ role: Owner, Committer, and Contributor. Additional permissions can
+ be granted to individual members, if needed.
+
+ <p>Most project owners will never need to grant any individual
+ member permissions. It is usually more important to describe
+ each member's duties in the notes.</p>
+
+ <div style="margin-top:.5em">
+ <a href="https://chromium.googlesource.com/infra/infra/+/main/appengine/monorail/doc/userguide/working-with-issues.md#Who-can-view-an-issue" target="new">Learn more</a>
+ <a href="http://code.google.com/p/monorail/wiki/Permissions" target="new"><img src="/static/images/tearoff_icon.gif" width="16" height="16"></a>
+ </div>
+ </div>
+ </td>
+</tr>
+
+
+<tr>
+ <th>Notes:</th>
+ <td>
+ [if-any offer_edit_member_notes]
+ <div style="width:40em">
+ <textarea style="width:100%" rows="4" class="ifExpand" name="notes"
+ >[member.notes]</textarea>
+ </div>
+ [else]
+ [if-any member.notes][member.notes][else]----[end]
+ [end]
+
+ </td>
+</tr>
+
+<tr>
+ <th>Autocomplete:</th>
+ <td>
+ [if-any perms.EditProject]
+ [define disable_checkbox]No[end]
+ [else]
+ [define disable_checkbox]Yes[end]
+ [end]
+ [if-any member.is_service_account]
+ [define disable_checkbox]Yes[end]
+ [end]
+ <div>
+ <input type="checkbox" name="ac_include" id="ac_include"
+ [if-any member.is_service_account][else]
+ [if-any member.ac_include]checked[end]
+ [end]
+ [is disable_checkbox "Yes"]disabled[end]
+ value="[member.user.user_id]"
+ >
+ <label for="ac_include">Include this member in autocomplete menus</label>
+ </div>
+ [if-any member.is_service_account]
+ <div>(service account is excluded by default)</div>
+ [end]
+
+ [if-any member.is_group]
+ <div>
+ <input type="checkbox" name="ac_expand" id="ac_expand"
+ [if-any member.ac_expand]checked[end]
+ [is disable_checkbox "Yes"]disabled[end]
+ value="[member.user.user_id]"
+ >
+ <label for="ac_expand">Expand this user group in autocomplete menus</label>
+ </div>
+ [else]
+ <input type="hidden" name="ac_expand" value="[member.user.user_id]">
+ [end]
+
+ </td>
+</tr>
+
+[if-any read_only]
+ <tr>
+ <th></th>
+ <td>
+ [include "../framework/read-only-rejection.ezt"]
+ </td>
+ </tr>
+[else]
+ [if-any offer_edit_perms offer_edit_member_notes]
+ <tr>
+ <th></th>
+ <td>
+ <input type="submit" name="submit" value="Save changes">
+ [if-any offer_remove_role]
+ <input type="submit" class="secondary" name="remove" value="Remove member"
+ id="remove_member">
+ [end]
+ </td>
+ </tr>
+ [end]
+[end]
+
+</table>
+</form>
+
+
+<script type="text/javascript" nonce="[nonce]">
+runOnLoad(function() {
+ function _confirmRemove() {
+ [if-any warn_abandonment]
+ [is total_num_owners "1"]
+ alert('You cannot remove the last project owner.');
+ return false;
+ [else]
+ return confirm('Remove yourself?\nYou will be locked out of making further changes.');
+ [end]
+ [else]
+ return confirm('Remove member [format "js"][member.user.email][end]?');
+ [end]
+ }
+
+ if ($("remove_member"))
+ $("remove_member").addEventListener("click", function(event) {
+ if (!_confirmRemove())
+ event.preventDefault();
+ });
+
+ [if-any read_only][else]
+ if ($("show_permissions"))
+ $("show_permissions").addEventListener("click", function() {
+ window.prpcClient.call(
+ 'monorail.Users', 'SetExpandPermsPreference', {expandPerms: true});
+ });
+ if ($("hide_permissions"))
+ $("hide_permissions").addEventListener("click", function() {
+ window.prpcClient.call(
+ 'monorail.Users', 'SetExpandPermsPreference', {expandPerms: false});
+ });
+ [end]
+
+});
+</script>
+
+[include "../framework/footer.ezt"]
diff --git a/templates/project/people-detail-perms-part.ezt b/templates/project/people-detail-perms-part.ezt
new file mode 100644
index 0000000..3a30417
--- /dev/null
+++ b/templates/project/people-detail-perms-part.ezt
@@ -0,0 +1,82 @@
+<table id="perm_defs" class="ifOpened">
+ [if-any offer_edit_perms displayed_extra_perms]
+ <tr><th colspan="2">Standard permissions</th></tr>
+ [end]
+
+ [include "people-detail-row-part.ezt" role_perms.View member_perms.View "View" "View issues"]
+ [include "people-detail-row-part.ezt" role_perms.Commit member_perms.Commit "Commit" "Full project member"]
+
+ [include "people-detail-row-part.ezt" role_perms.CreateIssue member_perms.CreateIssue "CreateIssue" "Enter a new issue"]
+ [include "people-detail-row-part.ezt" role_perms.AddIssueComment member_perms.AddIssueComment "AddIssueComment" "Add a comment to an issue"]
+ [include "people-detail-row-part.ezt" role_perms.EditIssue member_perms.EditIssue "EditIssue" "Edit any attribute of an issue"]
+ [include "people-detail-row-part.ezt" role_perms.EditIssueOwner member_perms.EditIssueOwner "EditIssueOwner" "- Edit the owner of an issue"]
+ [include "people-detail-row-part.ezt" role_perms.EditIssueSummary member_perms.EditIssueSummary "EditIssueSummary" "- Edit the summary of an issue"]
+ [include "people-detail-row-part.ezt" role_perms.EditIssueStatus member_perms.EditIssueStatus "EditIssueStatus" "- Edit the status of an issue"]
+ [include "people-detail-row-part.ezt" role_perms.EditIssueCc member_perms.EditIssueCc "EditIssueCc" "- Edit the CC list of an issue"]
+ [include "people-detail-row-part.ezt" role_perms.DeleteIssue member_perms.DeleteIssue "DeleteIssue" "Delete/undelete an issue"]
+
+ [include "people-detail-row-part.ezt" role_perms.DeleteAny member_perms.DeleteAny "DeleteAny" "Delete comments by anyone"]
+ [include "people-detail-row-part.ezt" role_perms.EditAnyMemberNotes member_perms.EditAnyMemberNotes "EditAnyMemberNotes" "Edit anyone's member notes"]
+ [include "people-detail-row-part.ezt" role_perms.ModerateSpam member_perms.ModerateSpam "ModerateSpam" "Mark or un-mark issues and comments as spam"]
+
+
+
+ [if-any offer_edit_perms displayed_extra_perms]
+ <tr><th colspan="2">Custom permissions</th></tr>
+ [end]
+
+ [if-any offer_edit_perms]
+ <tr>
+ <td id="displayed_extra_perms" colspan="2">
+ <div style="width:12em">
+ [for displayed_extra_perms]
+ <input style="width:100%" name="extra_perms"
+ value="[displayed_extra_perms]">
+ [end]
+ <input style="width:100%" name="extra_perms"
+ id="first_extra_perms"
+ value="" autocomplete="off">
+ </div>
+ </td>
+ </tr>
+ [else]
+ [for displayed_extra_perms]
+ <tr>
+ <td>
+ <input type="checkbox" checked="checked" disabled="disabled">
+ [displayed_extra_perms]
+ </td>
+ <td></td>
+ </tr>
+ [end]
+ [end]
+
+</table>
+
+<script type="text/javascript" nonce="[nonce]">
+runOnLoad(function() {
+ function _addInput(event) {
+ if (event.target.value == "") {
+ return;
+ }
+ var area = event.target.parentNode;
+ var newInput = document.createElement("input");
+ newInput.style.width = "100%";
+ newInput.name = event.target.name;
+ newInput.onfocus = function(e) {
+ _acrob(null);
+ _acof(e);
+ };
+ newInput.setAttribute("autocomplete", "off");
+ newInput.addEventListener("keyup", _addInput);
+ area.appendChild(newInput);
+ area.appendChild(document.createElement("br"));
+
+ // Make it only fire once.
+ event.target.removeEventListener("keyup", _addInput);
+ }
+
+ if ($("first_extra_perms"))
+ $("first_extra_perms").addEventListener("keyup", _addInput);
+});
+</script>
diff --git a/templates/project/people-detail-row-part.ezt b/templates/project/people-detail-row-part.ezt
new file mode 100644
index 0000000..785005f
--- /dev/null
+++ b/templates/project/people-detail-row-part.ezt
@@ -0,0 +1,29 @@
+[# Display one row in the permissions table.
+
+Args:
+ arg0: True if the permission is native to the role. So, it cannot be removed.
+ arg1: True if the user has this permission. So, it will be shown when not in editing mode.
+ arg2: Permission name.
+ arg3: Permission description.
+
+References globals:
+ offer_edit_perms: True if the user can edit permissions on this page.
+]
+
+<tr>
+ <td>
+ <input type="checkbox" [if-any arg1]checked="checked"[end] id="[arg2]"
+ [if-any offer_edit_perms]
+ [if-any arg0]
+ disabled="disabled"
+ [else]
+ name="extra_perms" value="[arg2]"
+ [end]
+ [else]
+ disabled="disabled"
+ [end]
+ >
+ <label for="[arg2]">[arg2]</label>
+ </td>
+ <td>[arg3]</td>
+</tr>
diff --git a/templates/project/people-list-page.ezt b/templates/project/people-list-page.ezt
new file mode 100644
index 0000000..f3756e8
--- /dev/null
+++ b/templates/project/people-list-page.ezt
@@ -0,0 +1,197 @@
+[define title]People[end]
+[define category_css]css/ph_list.css[end]
+[if-any is_hotlist][define category2_css]css/ph_detail.css[end][end]
+[include "../framework/header.ezt" "hidetabs"]
+[include "../framework/js-placeholders.ezt"]
+
+<form method="POST" action=[if-any is_hotlist]"people.do"[else]"list.do"[end] id="membership_form">
+<input type="hidden" name="token" value="[form_token]">
+[if-any newly_added_views]
+ <br/>
+ The following new members were successfully added:
+ <br/>
+ [for newly_added_views]
+ <a href="[newly_added_views.detail_url]">[newly_added_views.user.display_name]</a> ([newly_added_views.role])
+ <br/>
+ [end]
+ <br/>
+[end]
+
+<div id="colcontrol">
+ <div class="list">
+ [if-any pagination.visible]
+ <div class="pagination">
+ [if-any pagination.prev_url]<a href="[pagination.prev_url]"><b>‹</b> Prev</a>[end]
+ Members [pagination.start] - [pagination.last] of [pagination.total_count]
+ [if-any pagination.next_url]<a href="[pagination.next_url]">Next <b>›</b></a>[end]
+ </div>
+ [end]
+
+ <h4 style="display: inline">[if-any is_hotlist]Hotlist[else]Project[end] People</h4>
+
+ [if-any read_only][else]
+ [if-any offer_membership_editing]
+ <input type="button" value="Add members"
+ id="add_members_button" class="primary">
+ <input type="submit" value="Remove members"
+ id="removebtn" class="secondary" name="removebtn" disabled="disabled">
+ [# TOOD(jrobbins): extra confirmation when removing yourself as owner.]
+ [if-any is_hotlist]
+ <a id="transfer-ownership" class="buttonify">Transfer ownership</a>
+ [include "../features/transfer-hotlist-form.ezt"]
+ [end]
+ [end]
+ [if-any is_hotlist]
+ [if-any offer_remove_self]
+ <a id="remove-self" class="buttonify">Remove myself</a>
+ [include "../features/remove-self-hotlist-form.ezt"]
+ [end]
+ [end]
+ [end]
+ </div>
+
+ <table cellspacing="0" cellpadding="2" border="0" class="results striped vt" id="resultstable" width="100%">
+ <tbody>
+ [if-any pagination.visible_results]
+
+ <tr id="headingrow">
+ [if-any offer_membership_editing]
+ <th style="border-right:0; padding-right:2px"> </th>
+ [end]
+
+ <th style="white-space:nowrap">Name</th>
+ <th style="white-space:nowrap">Role</th>
+ [if-any is_hotlist]
+ [else]
+ <th style="white-space:nowrap">Autocomplete</th>
+ <th style="white-space:nowrap">Notes</th>
+ [end]
+ </tr>
+
+ [for pagination.visible_results]
+ [if-any is_hotlist]
+ [include "people-list-row-part.ezt" "hotlist"]
+ [else]
+ [include "people-list-row-part.ezt" "project"]
+ [end]
+ [end]
+
+ [else]
+ <tr>
+ <td colspan="40" class="id">
+ <div style="padding: 3em; text-align: center">
+ This [if-any is_hotlist]hotlist[else]project[end] does not have any members.
+ </div>
+ </td>
+ </tr>
+ [end]
+
+
+ </tbody>
+ </table>
+ <div class="list-foot">
+ <div class="pagination">
+ [if-any pagination.prev_url]<a href="[pagination.prev_url]"><b>‹</b> Prev</a>[end]
+ [pagination.start] - [pagination.last] of [pagination.total_count]
+ [if-any pagination.next_url]<a href="[pagination.next_url]">Next <b>›</b></a>[end]
+ </div>
+ </div>
+</div>
+
+[if-any untrusted_user_groups]
+ <div style="width:45em">
+ [include "untrusted-user-groups-part.ezt"]
+ </div>
+[end]
+
+[if-any read_only][else]
+ [if-any is_hotlist]
+ [include "people-add-members-form.ezt" "hotlist"]
+ [else]
+ [include "people-add-members-form.ezt" "project"]
+ [end]
+ [# TODO(jojwang): make more elegant later, just one line]
+[end]
+
+</form>
+
+[if-any offer_membership_editing]
+ <script type="text/javascript" nonce="[nonce]">
+runOnLoad(function() {
+ $("add_members_button").addEventListener("click", _openAddMembersForm);
+
+ function _countChecked(opt_className) {
+ var numChecked = 0;
+ var inputs = document.getElementsByTagName('input');
+ for (var i = 0; i < inputs.length; i++) {
+ var el = inputs[[]i];
+ if (el.type == 'checkbox' && el.name == 'remove' && el.checked &&
+ (!opt_className || opt_className == el.className)) {
+ numChecked++;
+ }
+ }
+ return numChecked;
+ }
+
+ function _enableRemoveButton() {
+ var removeButton = document.getElementById('removebtn');
+ if (_countChecked() > 0) {
+ removeButton.disabled = false;
+ } else {
+ removeButton.disabled = true;
+ }
+ }
+
+ setInterval(_enableRemoveButton, 700);
+
+ function _preventAbandonment(event) {
+ var meCheckbox = document.getElementById("me_checkbox");
+ if (meCheckbox && meCheckbox.checked) {
+ numOwnersChecked = _countChecked("owner");
+ if (numOwnersChecked == [total_num_owners]) {
+ alert("You cannot remove all project owners.");
+ event.preventDefault();
+ } else {
+ if (!confirm("Remove yourself as project owner?\n" +
+ "You will be locked out of making further changes.")) {
+ event.preventDefault();
+ }
+ }
+ }
+ return true;
+ }
+ [if-any check_abandonment]
+ $("membership_form").addEventListener("submit", _preventAbandonment);
+ [end]
+
+ [if-any is_hotlist]
+ initializeDialogBox("[hotlist_id]");
+ [end]
+});
+ </script>
+[end]
+[if-any is_hotlist][if-any offer_remove_self]
+ <script type="text/javascript" nonce="[nonce]">
+ runOnLoad(function () {initializeDialogBoxRemoveSelf()});
+ </script>
+[end][end]
+
+<script type="text/javascript" nonce="[nonce]">
+runOnLoad(function() {
+ function _handleResultsClick(event) {
+ var target = event.target;
+ if (target.tagName == "A")
+ return;
+ if (target.classList.contains("rowwidgets") || target.parentNode.classList.contains("rowwidgets"))
+ return;
+ if (target.tagName != "TR") target = target.parentNode;
+ _go(target.attributes[[]"data-url"].value,
+ (event.metaKey || event.ctrlKey || event.button == 1));
+ };
+ _addClickListener($("resultstable"), _handleResultsClick);
+
+});
+</script>
+
+
+[include "../framework/footer.ezt"]
diff --git a/templates/project/people-list-row-part.ezt b/templates/project/people-list-row-part.ezt
new file mode 100644
index 0000000..f30eaf5
--- /dev/null
+++ b/templates/project/people-list-row-part.ezt
@@ -0,0 +1,62 @@
+[define detail_url][pagination.visible_results.detail_url][end]
+<tr data-url="[detail_url]">
+
+ [if-any offer_membership_editing]
+ [is arg0 "hotlist"][is pagination.visible_results.role "Owner"]
+ <td style="padding-right:2px" class="rowwidgets"></td>
+ [else]
+ <td style="padding-right:2px" class="rowwidgets">
+ <input type="checkbox" name="remove"
+ value="[pagination.visible_results.user.email]"
+ >
+ </td>
+ [end]
+ [else]
+ <td style="padding-right:2px" class="rowwidgets">
+ <input type="checkbox" name="remove"
+ [is pagination.visible_results.role "Owner"]class="owner"[end]
+ value="[pagination.visible_results.user.email]"
+ [if-any pagination.visible_results.viewing_self]
+ id="me_checkbox"
+ [end]
+ >
+ </td>
+ [end][end]
+
+ <td style="white-space:nowrap; text-align:left;" class="id">
+ <a href="[detail_url]"
+ >[pagination.visible_results.user.display_name]</a>
+ [if-any pagination.visible_results.viewing_self]
+ <b>- me</b>
+ [end]
+ </td>
+
+ <td>
+ <a href="[detail_url]" style="white-space:nowrap">
+ [pagination.visible_results.role]<br>
+ [is arg0 "hotlist"][else]
+ [for pagination.visible_results.extra_perms]
+ <div style="font-size:90%">+ [pagination.visible_results.extra_perms]</div>
+ [end]
+ [end]
+ </a>
+ </td>
+
+ <td style="white-space:nowrap">
+ [is arg0 "hotlist"][else]
+ [if-any pagination.visible_results.is_service_account]
+ <a href="[detail_url]">Excluded</a>
+ [else][if-any pagination.visible_results.ac_include]
+ [# Nothing is displayed when the member is included.]
+ [else]
+ <a href="[detail_url]">Excluded</a>
+ [end][end]
+ [end]
+ </td>
+
+ [is arg0 "hotlist"][else]
+ <td width="90%">
+ <a href="[detail_url]">[pagination.visible_results.notes]</a>
+ </td>
+ [end]
+</tr>
diff --git a/templates/project/project-admin-advanced-page.ezt b/templates/project/project-admin-advanced-page.ezt
new file mode 100644
index 0000000..de91e40
--- /dev/null
+++ b/templates/project/project-admin-advanced-page.ezt
@@ -0,0 +1,11 @@
+[include "../framework/header.ezt" "showtabs"]
+
+ <form action="adminAdvanced.do" method="POST">
+ <input type="hidden" name="token" value="[form_token]">
+
+ [include "project-admin-publishing-part.ezt"]
+ [include "project-admin-quota-part.ezt"]
+
+ </form>
+
+[include "../framework/footer.ezt"]
diff --git a/templates/project/project-admin-page.ezt b/templates/project/project-admin-page.ezt
new file mode 100644
index 0000000..84c001f
--- /dev/null
+++ b/templates/project/project-admin-page.ezt
@@ -0,0 +1,134 @@
+[define category_css]css/ph_detail.css[end]
+[include "../framework/header.ezt" "showtabs"]
+
+[if-any read_only][include "../framework/read-only-rejection.ezt"]
+[else]
+
+ <form action="admin.do" method="POST" autocomplete="off" enctype="multipart/form-data">
+ <input type="hidden" name="token" value="[form_token]">
+
+<h4>Project metadata</h4>
+
+<div class="section">
+ [include "../framework/project-descriptive-fields.ezt"]
+</div>
+
+
+<h4>Project access</h4>
+
+<div class="section">
+ [if-any offer_access_level initial_access]
+ <br>This project may be viewed by:
+ [include "../framework/project-access-part.ezt" "dontchecksubmit"]<br>
+ [end]
+
+<div class="section">
+ <div class="closed">
+ <p>Restriction labels allow project members to restrict access to individual
+ issues.
+ <a class="ifClosed toggleHidden" href="#" style="font-size:90%; margin-left:.5em">Learn more</a></p>
+ <div class="ifOpened help">
+ Normally, if a project member may edit the labels, then they may also
+ edit restriction labels. That allows project committers to adjust access
+ controls for the items that they are working on. However, some project
+ owners may prefer that once a restriction label is in place, only a project
+ owner may remove it.
+ </div>
+ </div>
+ <input type="checkbox" name="only_owners_remove_restrictions"
+ id="only_owners_remove_restrictions"
+ [if-any only_owners_remove_restrictions]checked="checked"[end] >
+ <label for="only_owners_remove_restrictions">Only project owners
+ may remove <tt>Restrict-*</tt> labels</label>
+</div>
+
+<div class="section">
+ <div class="closed">
+ <p>Collaboration style
+ <a class="ifClosed toggleHidden" href="#" style="font-size:90%; margin-left:.5em">Learn more</a></p>
+ <div class="ifOpened help">
+ Project workspaces are usually intended to promote collaboration among
+ all project members. However, sometimes a compartmentalized collaboration
+ style is more appropriate. For example, one company might want to work
+ with several partners, but not let each partner know about the others.
+ Note: In such a project, all artifacts should have restriction labels.
+ </div>
+ </div>
+ <input type="checkbox" name="only_owners_see_contributors" id="only_owners_see_contributors"
+ [if-any only_owners_see_contributors]checked="checked"[end] >
+ <label for="only_owners_see_contributors">Only project owners may see the list of contributors.</label>
+</div>
+
+</div>
+
+
+<h4>Activity notifications</h4>
+
+<div class="section">
+ <p>Email notifications of issue tracker activity will automatically be sent to
+ the following email address.</p>
+
+ <table cellpadding="2">
+ <tr><th>All issue changes:</th>
+ <td><input type="email" name="issue_notify" size="35" value="[issue_notify]"><br>
+ [if-any errors.issue_notify]
+ <div class="fielderror">[errors.issue_notify]</div>
+ [end]
+ </td>
+ </tr>
+ </table>
+ [# TODO: validate as address is entered ]
+
+ [include "../framework/admin-email-sender-part.ezt"]
+
+ <div class="closed">
+ <p>Notification contents
+ <a class="ifClosed toggleHidden" href="#" style="font-size:90%; margin-left:.5em">Learn more</a></p>
+ <div class="ifOpened help">
+ By default, notifications content will be limited based on user preference,
+ Restrict-* labels, and their membership in a given project. This option
+ forces the full notification content to be sent regardless of other factors.
+ </div>
+ </div>
+ <input type="checkbox" name="issue_notify_always_detailed" id="issue_notify_always_detailed"
+ [if-any issue_notify_always_detailed]checked="checked"[end] >
+ <label for="issue_notify_always_detailed">Always send detailed notification content.</label>
+</div>
+
+
+<h4>Email reply processing</h4>
+
+<div class="section">
+ <div class="closed">
+ <p>Users may add comments and make updates by replying to
+ certain notification emails.
+ <a class="ifClosed toggleHidden" style="font-size:90%; margin-left:.5em">Learn more</a></p>
+ <div class="ifOpened help">
+ Users may add comments to an issue
+ by replying to a notification email:
+
+ <ul>
+ <li>Look for a note in the footer of the email indicating that
+ a reply will be processed by the server.</li>
+ <li>Comments must be in replies to notification emails sent directly
+ to the member, not through a mailing list.</li>
+ <li>The reply must be <tt>From:</tt> the same email address to which
+ the notification was sent.</li>
+ <li>Project members who have permission to edit issues may make
+ changes via email replies.</li>
+ </ul>
+ </div>
+ </div>
+ <input type="checkbox" name="process_inbound_email" id="process_inbound_email"
+ [if-any process_inbound_email]checked="checked"[end] >
+ <label for="process_inbound_email">Process email replies</label>
+</div>
+
+<br>
+
+ <input type="submit" id="savechanges" name="btn" value="Save changes" class="submit">
+ </form>
+
+[end]
+
+[include "../framework/footer.ezt"]
diff --git a/templates/project/project-admin-publishing-part.ezt b/templates/project/project-admin-publishing-part.ezt
new file mode 100644
index 0000000..bef52df
--- /dev/null
+++ b/templates/project/project-admin-publishing-part.ezt
@@ -0,0 +1,110 @@
+[# This is the "Project publishing options" on the "Advanced" subtab. ]
+
+<h4>Project state</h4>
+
+<div class="section">
+<table class="vt" cellspacing="20" style="width:60em">
+ [if-any offer_archive]
+ <tr>
+ <td>
+ <input type="submit" name="archivebtn" style="width:6em"
+ value="Archive">
+ </td>
+ <td>
+ Archive this project. It will only be visible read-only to
+ project members. Once it is archived, you may unarchive it, or go ahead
+ and fully delete it.
+ <br><br>
+ </td>
+ </tr>
+ [end]
+
+ [if-any offer_delete]
+ <tr>
+ <td>
+ <input type="submit" name="deletebtn" style="width:6em"
+ value="Delete" id="delbtn">
+ </td>
+ <td>
+ Completely delete this project now.
+ <br><br>
+ </td>
+ </tr>
+ [end]
+
+ [if-any offer_publish]
+ <tr>
+ <td>
+ <input type="submit" name="publishbtn" style="width:6em"
+ value="Unarchive">
+ </td>
+ <td>
+ Make this project active again.
+ All project contents will become visible and editable to users as normal.
+ <br><br>
+ </td>
+ </tr>
+ [end]
+
+ [if-any offer_move]
+ <tr>
+ <td>
+ <input type="submit" name="movedbtn" style="width:6em"
+ value="Move">
+ </td>
+ <td>
+ If you have moved your project to a different location, enter it here and
+ users will be directed to that location. If the destination is another
+ project on this site, enter just the new project name. If the destination
+ is another site, enter the new project home page URL.
+ <br><br>
+ <b>Location:</b>
+ <input type="text" name="moved_to" size="50" value="[moved_to]">
+ </td>
+ </tr>
+ [end]
+
+ [if-any offer_doom]
+ <tr>
+ <td>
+ <input type="submit" name="doombtn" style="width:6em"
+ value="Doom">
+ </td>
+ <td>
+ Immediately archive this project and schedule it for deletion in
+ 90 days. Only a site admin can un-archive the project, not a
+ project owner. In the meantime, the project will be read-only for
+ project members only, and the reason for deletion will be displayed at the top
+ of each page.
+ <br><br>
+ <b>Reason:</b>
+ <input type="text" name="reason" size="50" value="[default_doom_reason]">
+ </td>
+ </tr>
+ [end]
+
+ [if-any offer_archive offer_delete offer_publish offer_doom offer_move][else]
+ <tr>
+ <td>
+ </td>
+ <td>
+ You are not authorized to change the project state.
+ </td>
+ </tr>
+ [end]
+
+</table>
+
+</div>
+
+<script type="text/javascript" nonce="[nonce]">
+runOnLoad(function() {
+ if ($("delbtn")) {
+ $("delbtn").addEventListener("click", function(event) {
+ var msg = "Really delete the whole project?\nThis operation cannot be undone.";
+ if (!confirm(msg))
+ event.preventDefault();
+ });
+ }
+});
+</script>
diff --git a/templates/project/project-admin-quota-part.ezt b/templates/project/project-admin-quota-part.ezt
new file mode 100644
index 0000000..1649eab
--- /dev/null
+++ b/templates/project/project-admin-quota-part.ezt
@@ -0,0 +1,30 @@
+<h4>Storage quota</h4>
+
+<div class="section">
+
+ <table cellspacing="6" style="padding:6px">
+ <tr>
+ <td>Issue attachments:</td>
+ <td>[include "quota-bar.ezt" attachment_quota]</td>
+ </tr>
+ <tr>
+ <td style="padding:15px 0">
+ [if-any offer_quota_editing]
+ <input type="submit" name="savechanges" value="Update Quota">
+ [end]
+ </td>
+ <td style="padding:15px 0">
+ [if-any offer_quota_editing]
+ <input type="number" name="[attachment_quota.field_name]" value="[attachment_quota.quota_mb]"
+ size="5" min="1" style="font-size:90%; padding:0">
+ [if-any errors.attachment_quota]
+ <div class="fielderror">[errors.attachment_quota]</div>
+ [end]
+ [else]
+ [attachment_quota.quota_mb]
+ [end]
+ MB
+ </td>
+ </tr>
+ </table>
+</div>
diff --git a/templates/project/project-export-page.ezt b/templates/project/project-export-page.ezt
new file mode 100644
index 0000000..487b051
--- /dev/null
+++ b/templates/project/project-export-page.ezt
@@ -0,0 +1,23 @@
+[define category_css]css/ph_detail.css[end]
+[include "../framework/header.ezt" "showtabs"]
+
+<h3>Project export</h3>
+
+<form action="projectExport/json" method="GET">
+ [# We use xhr_token here because we are doing a GET on a JSON servlet.]
+ <input type="hidden" name="token" value="[xhr_token]">
+ <table cellpadding="3" class="rowmajor vt">
+ <tr>
+ <th>Format</th>
+ <td style="width:90%">JSON</td>
+ </tr>
+ <tr>
+ <th></th>
+ <td><input type="submit" name="btn" value="Submit"></td>
+ </tr>
+ </table>
+</form>
+
+
+
+[include "../framework/footer.ezt"]
diff --git a/templates/project/project-summary-page.ezt b/templates/project/project-summary-page.ezt
new file mode 100644
index 0000000..4c45bd3
--- /dev/null
+++ b/templates/project/project-summary-page.ezt
@@ -0,0 +1,102 @@
+[define category_css]css/ph_detail.css[end]
+[include "../framework/header.ezt" "showtabs"]
+[# TODO: add UI element permissions when I add editing elements to this page. ]
+[define show_star][if-any project_stars_enabled][if-any logged_in_user][if-any read_only][else]yes[end][end][end][end]
+
+<h4>Project: [projectname]</h4>
+<div class="section">
+ <div><i>[project_summary]</i></div>
+
+ [if-any show_star]
+ <div>
+ <a class="star" id="star"
+ style="color:[if-any is_project_starred]cornflowerblue[else]gray[end];"
+ title="[if-any is_project_starred]Un-s[else]S[end]tar this project">
+ [if-any is_project_starred]★[else]☆[end]
+ </a>
+ Starred by [num_stars] user[plural]
+ </div>
+ [end]
+</div>
+
+
+<h4>Project description</h4>
+<div class="section">
+ [format "raw"][formatted_project_description][end]
+</div>
+
+<h4>Project access</h4>
+<div class="section">
+ [access_level.name]
+</div>
+
+
+[if-any home_page]
+ <h4>Project home page</h4>
+ <div class="section">
+ <a href="[home_page]">[home_page]</a>
+ </div>
+[end]
+
+[if-any docs_url]
+ <h4>Project documentation</h4>
+ <div class="section">
+ <a href="[docs_url]">[docs_url]</a>
+ </div>
+[end]
+
+[if-any source_url]
+ <h4>Project source browser</h4>
+ <div class="section">
+ <a href="[source_url]">[source_url]</a>
+ </div>
+[end]
+
+<!-- TODO(jrobbins): expose this later when it is more fully baked.
+
+<h4>Issue tracking process</h4>
+<div class="section">
+ Brief paragraph about how you intend this issue tracker to be used.
+
+</div>
+
+
+<h4>Ground rules</h4>
+ <ul>
+ <li>Non-members may enter new issues, but they will be moderated...</li>
+ <li>Please keep to the facts of the issue, don't try to advocate.</li>
+ <li>We are not currently looking for feature requests from non-members.</li>
+ </ul>
+
+
+
+<h4>Guidelines</h4>
+ <ul>
+ <li>Make sure the defect is verified with the latest build</li>
+ <li>Another bullet item describing how to collaborate in this project</li>
+ <li>A few more</li>
+ <li>And going into a little detail</li>
+ <li>But not too much... also need good defaults and examples</li>
+ </ul>
+
+
+<h4>For more information</h4>
+ <ul>
+ <li>Link to external docs</li>
+ <li>And discussion forums</li>
+ </ul>
+
+-->
+
+<script type="text/javascript" nonce="[nonce]">
+runOnLoad(function() {
+ if ($("star")) {
+ [# The user viewing this page wants to star the project *on* this page]
+ $("star").addEventListener("click", function () {
+ _TKR_toggleStar($("star"), "[projectname]");
+ });
+ }
+});
+</script>
+
+[include "../framework/footer.ezt"]
diff --git a/templates/project/project-updates-page.ezt b/templates/project/project-updates-page.ezt
new file mode 100644
index 0000000..c3ee3b4
--- /dev/null
+++ b/templates/project/project-updates-page.ezt
@@ -0,0 +1,7 @@
+[define page_css]css/d_updates_page.css[end]
+
+[include "../framework/header.ezt" "hidetabs"]
+
+[include "../features/updates-page.ezt"]
+
+[include "../framework/footer.ezt"]
diff --git a/templates/project/quota-bar.ezt b/templates/project/quota-bar.ezt
new file mode 100644
index 0000000..e89a6e2
--- /dev/null
+++ b/templates/project/quota-bar.ezt
@@ -0,0 +1,22 @@
+[# Display a little HTML bar and labels. This is not really a bar chart.
+ For comparison, see the bars in the top half of
+ https://www.google.com/accounts/ManageStorage
+
+arg0: an EZTItem with quota info for one component.
+]
+
+<table border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td style="width:200px">
+ <table border="0" cellpadding="0" cellspacing="0" style="width:100%; border:1px solid #345BA6">
+ <tr>
+ <td style="background:#345BA6; width:[arg0.used_percent]%"> </td>
+ <td style="background:#EBF0FA; width:[arg0.avail_percent]%"> </td>
+ </tr>
+ </table>
+ </td>
+ <td style="padding-left:.7em">
+ [arg0.used] ([arg0.used_percent]%) in use
+ </td>
+ </tr>
+</table>
diff --git a/templates/project/rules-deleted-notification-email.ezt b/templates/project/rules-deleted-notification-email.ezt
new file mode 100644
index 0000000..2155004
--- /dev/null
+++ b/templates/project/rules-deleted-notification-email.ezt
@@ -0,0 +1,6 @@
+The following Filter rules were deleted for the [project_name] project.
+
+[for rules] <div>[rules]</div> [end]
+
+If these rules need to be added back please re-create them <a href="[rules_url]">here</a>
+<br>
diff --git a/templates/project/untrusted-user-groups-part.ezt b/templates/project/untrusted-user-groups-part.ezt
new file mode 100644
index 0000000..474cfe7
--- /dev/null
+++ b/templates/project/untrusted-user-groups-part.ezt
@@ -0,0 +1,14 @@
+[if-any perms.EditProject]
+ <div class="help" style="background: #ddf8cc;">
+ <b>Important:</b> Users could be given indirect
+ roles in this project without your knowledge.
+ The following user groups either have group managers
+ who are not project owners in this project, or they allow anyone to
+ join the group:
+ <ul style="list-style-type: none">
+ [for untrusted_user_groups]
+ <li>[untrusted_user_groups.email]</li> [# TODO(jrobbins): hyperlink]
+ [end]
+ </ul>
+ </div>
+[end]