[CalendarServer-changes] [12853] CalendarServer/trunk/calendarserver/webadmin
source_changes at macosforge.org
source_changes at macosforge.org
Fri Mar 7 16:08:43 PST 2014
Revision: 12853
http://trac.calendarserver.org//changeset/12853
Author: wsanchez at apple.com
Date: 2014-03-07 16:08:43 -0800 (Fri, 07 Mar 2014)
Log Message:
-----------
Jettison a bunch of ballast.
Modified Paths:
--------------
CalendarServer/trunk/calendarserver/webadmin/landing.py
CalendarServer/trunk/calendarserver/webadmin/resource.py
Removed Paths:
-------------
CalendarServer/trunk/calendarserver/webadmin/template.html
Modified: CalendarServer/trunk/calendarserver/webadmin/landing.py
===================================================================
--- CalendarServer/trunk/calendarserver/webadmin/landing.py 2014-03-07 23:09:08 UTC (rev 12852)
+++ CalendarServer/trunk/calendarserver/webadmin/landing.py 2014-03-08 00:08:43 UTC (rev 12853)
@@ -26,7 +26,6 @@
# from twisted.web.template import renderer
from .resource import PageElement, TemplateResource
-from .resource import WebAdminResource
from .logs import LogsResource
from .principals import PrincipalsResource
from .work import WorkMonitorResource
@@ -72,14 +71,7 @@
self.putChild(u"principals", PrincipalsResource(directory))
self.putChild(u"work", WorkMonitorResource(store))
- self.putChild(
- u"old",
- WebAdminResource(
- path, root, directory, store, principalCollections
- )
- )
-
def getChild(self, name):
bound = super(WebAdminLandingResource, self).getChild(name)
Modified: CalendarServer/trunk/calendarserver/webadmin/resource.py
===================================================================
--- CalendarServer/trunk/calendarserver/webadmin/resource.py 2014-03-07 23:09:08 UTC (rev 12852)
+++ CalendarServer/trunk/calendarserver/webadmin/resource.py 2014-03-08 00:08:43 UTC (rev 12853)
@@ -20,712 +20,23 @@
"""
__all__ = [
- "WebAdminResource",
- "WebAdminPage",
+ "PageElement",
"TemplateResource",
]
-import operator
-import urlparse
-
-from zope.interface.declarations import implements
-
-from twisted.internet.defer import inlineCallbacks, returnValue, succeed
+from twisted.internet.defer import inlineCallbacks, returnValue
from twisted.python.modules import getModule
+from twisted.web.template import (
+ Element, renderer, XMLFile, flattenString, tags
+)
+
from txweb2.stream import MemoryStream
from txweb2.resource import Resource
from txweb2.http import Response
from txweb2.http_headers import MimeType
-from txweb2.http import HTTPError
-from txdav.xml import element as davxml
-from twisted.web.iweb import ITemplateLoader
-from twisted.web.template import (
- Element, renderer, XMLFile, flattenString, tags
-)
-from twistedcaldav.config import config
-from twistedcaldav.extensions import DAVFile, ReadOnlyResourceMixIn
-from calendarserver.tools.util import (
- principalForPrincipalID, proxySubprincipal, action_addProxyPrincipal,
- action_removeProxyPrincipal
-)
-
-
-
-class WebAdminPage(Element):
- """
- Web administration renderer for HTML.
-
- @ivar resource: a L{WebAdminResource}.
- """
-
- loader = XMLFile(
- getModule(__name__).filePath.sibling("template.html")
- )
-
- def __init__(self, resource):
- super(WebAdminPage, self).__init__()
- self.resource = resource
-
-
- @renderer
- def main(self, request, tag):
- """
- Main renderer, which fills page-global slots like 'title'.
- """
- searchTerm = request.args.get('resourceSearch', [''])[0]
- return tag.fillSlots(resourceSearch=searchTerm)
-
-
- @renderer
- @inlineCallbacks
- def hasSearchResults(self, request, tag):
- """
- Renderer which detects if there are resource search results and
- continues if so.
- """
- if 'resourceSearch' not in request.args:
- returnValue('')
- if (yield self.performSearch(request)):
- returnValue(tag)
- else:
- returnValue('')
-
-
- @renderer
- @inlineCallbacks
- def noSearchResults(self, request, tag):
- """
- Renderer which detects if there are resource search results and
- continues if so.
- """
- if 'resourceSearch' not in request.args:
- returnValue('')
- rows = yield self.performSearch(request)
- if rows:
- returnValue("")
- else:
- returnValue(tag)
-
- _searchResults = None
-
- @inlineCallbacks
- def performSearch(self, request):
- """
- Perform a directory search for users, groups, and resources based on
- the resourceSearch query parameter. Cache the results of that search
- so that it will only be done once per request.
- """
- if self._searchResults is not None:
- returnValue(self._searchResults)
- searchTerm = request.args.get('resourceSearch', [''])[0]
- if searchTerm:
- results = sorted((yield self.resource.search(searchTerm)),
- key=lambda record: record.shortNames[0])
- else:
- results = []
- self._searchResults = results
- returnValue(results)
-
-
- @renderer
- def searchResults(self, request, tag):
- """
- Renderer which renders resource search results.
- """
- d = self.performSearch(request)
- return d.addCallback(searchToSlots, tag)
-
-
- @renderer
- def resourceDetails(self, request, tag):
- """
- Renderer which fills slots for details of the resource selected by
- the resourceId request parameter.
- """
- resourceId = request.args.get('resourceId', [''])[0]
- propertyName = request.args.get('davPropertyName', [''])[0]
- proxySearch = request.args.get('proxySearch', [''])[0]
- if resourceId:
- principalResource = self.resource.getResourceById(
- request, resourceId)
- return DetailsElement(
- resourceId, principalResource, propertyName, proxySearch, tag,
- self.resource
- )
- else:
- return ""
-
-
-
-def searchToSlots(results, tag):
- """
- Convert the result of doing a search to an iterable of tags.
- """
- for idx, record in enumerate(results):
- yield tag.clone().fillSlots(
- rowClass="even" if (idx % 2 == 0) else "odd",
- type=record.recordType,
- shortName=record.shortNames[0],
- name=record.fullName,
- typeStr={
- "users": "User",
- "groups": "Group",
- "locations": "Place",
- "resources": "Resource",
- }.get(record.recordType, repr(record.recordType)),
- shortNames=str(", ".join(record.shortNames)),
- authIds=str(", ".join(record.authIDs)),
- emails=str(", ".join(record.emailAddresses)),
- )
-
-
-
-class stan(object):
- """
- L{ITemplateLoader} wrapper for an existing tag, in the style of Nevow's
- 'stan' loader.
- """
- implements(ITemplateLoader)
-
- def __init__(self, tag):
- self.tag = tag
-
-
- def load(self):
- return self.tag
-
-
-
-class DetailsElement(Element):
-
- def __init__(self, resourceId, principalResource, davPropertyName,
- proxySearch, tag, adminResource):
- self.principalResource = principalResource
- self.adminResource = adminResource
- self.proxySearch = proxySearch
- tag.fillSlots(resourceTitle=unicode(principalResource),
- resourceId=resourceId,
- davPropertyName=davPropertyName,
- proxySearch=proxySearch)
- try:
- namespace, name = davPropertyName.split("#")
- except Exception:
- self.namespace = None
- self.name = None
- if davPropertyName:
- self.error = davPropertyName
- else:
- self.error = None
- else:
- self.namespace = namespace
- self.name = name
- self.error = None
-
- super(DetailsElement, self).__init__(loader=stan(tag))
-
-
- @renderer
- def propertyParseError(self, request, tag):
- """
- Renderer to display an error when the user specifies an invalid
- property name.
- """
- if self.error is None:
- return ""
- else:
- return tag.fillSlots(davPropertyName=self.error)
-
-
- @renderer
- @inlineCallbacks
- def davProperty(self, request, tag):
- """
- Renderer to display an error when the user specifies an invalid
- property name.
- """
- if self.name is not None:
- try:
- propval = yield self.principalResource.readProperty(
- (self.namespace, self.name), request
- )
- except HTTPError:
- propval = "No such property: " + "#".join([self.namespace,
- self.name])
- else:
- propval = propval.toxml()
- returnValue(tag.fillSlots(value=propval))
- else:
- returnValue("")
-
-
- @renderer
- def autoSchedule(self, request, tag):
- """
- Renderer which elides its tag for non-resource-type principals.
- """
- if (
- self.principalResource.record.recordType != "users" and
- self.principalResource.record.recordType != "groups" or
- self.principalResource.record.recordType == "users" and
- config.Scheduling.Options.AutoSchedule.AllowUsers
- ):
- return tag
- return ""
-
-
- @renderer
- def isAutoSchedule(self, request, tag):
- """
- Renderer which sets the 'selected' attribute on its tag if the resource
- is auto-schedule.
- """
- if self.principalResource.getAutoSchedule():
- tag(selected='selected')
- return tag
-
-
- @renderer
- def isntAutoSchedule(self, request, tag):
- """
- Renderer which sets the 'selected' attribute on its tag if the resource
- is not auto-schedule.
- """
- if not self.principalResource.getAutoSchedule():
- tag(selected='selected')
- return tag
-
-
- @renderer
- def autoScheduleModeDefault(self, request, tag):
- """
- Renderer which sets the 'selected' attribute on its tag based on the
- resource auto-schedule-mode.
- """
- if self.principalResource.getAutoScheduleMode() == "default":
- tag(selected='selected')
- return tag
-
-
- @renderer
- def autoScheduleModeNone(self, request, tag):
- """
- Renderer which sets the 'selected' attribute on its tag based on the
- resource auto-schedule-mode.
- """
- if self.principalResource.getAutoScheduleMode() == "none":
- tag(selected='selected')
- return tag
-
-
- @renderer
- def autoScheduleModeAcceptAlways(self, request, tag):
- """
- Renderer which sets the 'selected' attribute on its tag based on the
- resource auto-schedule-mode.
- """
- if self.principalResource.getAutoScheduleMode() == "accept-always":
- tag(selected='selected')
- return tag
-
-
- @renderer
- def autoScheduleModeDeclineAlways(self, request, tag):
- """
- Renderer which sets the 'selected' attribute on its tag based on the
- resource auto-schedule-mode.
- """
- if self.principalResource.getAutoScheduleMode() == "decline-always":
- tag(selected='selected')
- return tag
-
-
- @renderer
- def autoScheduleModeAcceptIfFree(self, request, tag):
- """
- Renderer which sets the 'selected' attribute on its tag based on the
- resource auto-schedule-mode.
- """
- if self.principalResource.getAutoScheduleMode() == "accept-if-free":
- tag(selected='selected')
- return tag
-
-
- @renderer
- def autoScheduleModeDeclineIfBusy(self, request, tag):
- """
- Renderer which sets the 'selected' attribute on its tag based on the
- resource auto-schedule-mode.
- """
- if self.principalResource.getAutoScheduleMode() == "decline-if-busy":
- tag(selected='selected')
- return tag
-
-
- @renderer
- def autoScheduleModeAutomatic(self, request, tag):
- """
- Renderer which sets the 'selected' attribute on its tag based on the
- resource auto-schedule-mode.
- """
- if (
- self.principalResource.getAutoScheduleMode() == "automatic" or
- not self.principalResource.getAutoScheduleMode()
- ):
- tag(selected='selected')
- return tag
-
- _matrix = None
-
- @inlineCallbacks
- def proxyMatrix(self, request):
- """
- Compute a matrix of proxies to display in a 2-column table.
-
- This value is cached so that multiple renderers may refer to it without
- causing additional back-end queries.
-
- @return: a L{Deferred} which fires with a list of 2-tuples of
- (readProxy, writeProxy). If there is an unequal number of read and
- write proxies, the tables will be padded out with C{None}s so that
- some readProxy or writeProxy values will be C{None} at the end of
- the table.
- """
- if self._matrix is not None:
- returnValue(self._matrix)
- (readSubPrincipal, writeSubPrincipal) = (
- proxySubprincipal(self.principalResource, "read"),
- proxySubprincipal(self.principalResource, "write")
- )
- if readSubPrincipal or writeSubPrincipal:
- (readMembers, writeMembers) = (
- (yield readSubPrincipal.readProperty(davxml.GroupMemberSet,
- None)),
- (yield writeSubPrincipal.readProperty(davxml.GroupMemberSet,
- None))
- )
- if readMembers.children or writeMembers.children:
- # FIXME: 'else' case needs to be handled by separate renderer
- readProxies = []
- writeProxies = []
-
- def getres(ref):
- return self.adminResource.getResourceById(request,
- str(proxyHRef))
- for proxyHRef in sorted(readMembers.children, key=str):
- readProxies.append((yield getres(proxyHRef)))
- for proxyHRef in sorted(writeMembers.children, key=str):
- writeProxies.append((yield getres(proxyHRef)))
- lendiff = len(readProxies) - len(writeProxies)
- if lendiff > 0:
- writeProxies += [None] * lendiff
- elif lendiff < 0:
- readProxies += [None] * -lendiff
- self._matrix = zip(readProxies, writeProxies)
- else:
- self._matrix = []
- else:
- self._matrix = []
- returnValue(self._matrix)
-
-
- @renderer
- @inlineCallbacks
- def noProxies(self, request, tag):
- """
- Renderer which shows its tag if there are no proxies for this resource.
- """
- mtx = yield self.proxyMatrix(request)
- if mtx:
- returnValue("")
- returnValue(tag)
-
-
- @renderer
- @inlineCallbacks
- def hasProxies(self, request, tag):
- """
- Renderer which shows its tag if there are any proxies for this
- resource.
- """
- mtx = yield self.proxyMatrix(request)
- if mtx:
- returnValue(tag)
- returnValue("")
-
-
- @renderer
- @inlineCallbacks
- def noProxyResults(self, request, tag):
- """
- Renderer which shows its tag if there are no proxy search results for
- this request.
- """
- if not self.proxySearch:
- returnValue("")
- results = yield self.performProxySearch()
- if results:
- returnValue("")
- else:
- returnValue(tag)
-
-
- @renderer
- @inlineCallbacks
- def hasProxyResults(self, request, tag):
- """
- Renderer which shows its tag if there are any proxy search results for
- this request.
- """
- results = yield self.performProxySearch()
- if results:
- returnValue(tag)
- else:
- returnValue("")
-
-
- @renderer
- @inlineCallbacks
- def proxyRows(self, request, tag):
- """
- Renderer which does zipping logic to render read-only and read-write
- rows of existing proxies for the currently-viewed resource.
- """
- result = []
- mtx = yield self.proxyMatrix(request)
- for idx, (readProxy, writeProxy) in enumerate(mtx):
- result.append(ProxyRow(tag.clone(), idx, readProxy, writeProxy))
- returnValue(result)
-
- _proxySearchResults = None
-
- def performProxySearch(self):
- if self._proxySearchResults is not None:
- return succeed(self._proxySearchResults)
-
- if self.proxySearch:
- def nameSorted(records):
- records.sort(key=operator.attrgetter('fullName'))
- self._proxySearchResults = records
- return records
- return self.adminResource.search(
- self.proxySearch).addCallback(nameSorted)
- else:
- return succeed([])
-
-
- @renderer
- def proxySearchRows(self, request, tag):
- """
- Renderer which renders search results for the proxy form.
- """
- d = self.performProxySearch()
- return d.addCallback(searchToSlots, tag)
-
-
-
-class ProxyRow(Element):
-
- def __init__(self, tag, index, readProxy, writeProxy):
- tag.fillSlots(rowClass="even" if (index % 2 == 0) else "odd")
- super(ProxyRow, self).__init__(loader=stan(tag))
- self.readProxy = readProxy
- self.writeProxy = writeProxy
-
-
- def proxies(self, proxyResource, tag):
- if proxyResource is None:
- return ''
- return tag.fillSlots(proxy=str(proxyResource),
- type=proxyResource.record.recordType,
- shortName=proxyResource.record.shortNames[0])
-
-
- def noProxies(self, proxyResource, tag):
- if proxyResource is None:
- return tag
- else:
- return ""
-
-
- @renderer
- def readOnlyProxies(self, request, tag):
- return self.proxies(self.readProxy, tag)
-
-
- @renderer
- def noReadOnlyProxies(self, request, tag):
- return self.noProxies(self.readProxy, tag)
-
-
- @renderer
- def readWriteProxies(self, request, tag):
- return self.proxies(self.writeProxy, tag)
-
-
- @renderer
- def noReadWriteProxies(self, request, tag):
- return self.noProxies(self.writeProxy, tag)
-
-
-
-class WebAdminResource (ReadOnlyResourceMixIn, DAVFile):
- """
- Web administration HTTP resource.
- """
-
- def __init__(self, path, root, directory, store, principalCollections=()):
- self.root = root
- self.directory = directory
- self.store = store
- super(WebAdminResource, self).__init__(
- path, principalCollections=principalCollections
- )
-
-
- # Only allow administrators to access
- def defaultAccessControlList(self):
- return davxml.ACL(*config.AdminACEs)
-
-
- def etag(self):
- # Can't be calculated here
- return succeed(None)
-
-
- def contentLength(self):
- # Can't be calculated here
- return None
-
-
- def lastModified(self):
- return None
-
-
- def exists(self):
- return True
-
-
- def displayName(self):
- return "Web Admin"
-
-
- def contentType(self):
- return MimeType.fromString("text/html; charset=utf-8")
-
-
- def contentEncoding(self):
- return None
-
-
- def createSimilarFile(self, path):
- return DAVFile(path, principalCollections=self.principalCollections())
-
-
- @inlineCallbacks
- def resourceActions(self, request, principal):
- """
- Take all actions on the given principal based on the given request.
- """
-
- def queryValue(arg):
- return request.args.get(arg, [""])[0]
-
- def queryValues(arg):
- query = urlparse.parse_qs(urlparse.urlparse(request.uri).query,
- True)
- matches = []
- for key in query.keys():
- if key.startswith(arg):
- matches.append(key[len(arg):])
- return matches
-
- autoSchedule = queryValue("autoSchedule")
- autoScheduleMode = queryValue("autoScheduleMode")
- makeReadProxies = queryValues("mkReadProxy|")
- makeWriteProxies = queryValues("mkWriteProxy|")
- removeProxies = queryValues("rmProxy|")
-
- # Update the auto-schedule value if specified.
- if autoSchedule is not None and (autoSchedule == "true" or
- autoSchedule == "false"):
- if (
- principal.record.recordType != "users" and
- principal.record.recordType != "groups" or
- principal.record.recordType == "users" and
- config.Scheduling.Options.AutoSchedule.AllowUsers
- ):
- yield principal.setAutoSchedule(autoSchedule == "true")
- yield principal.setAutoScheduleMode(autoScheduleMode)
-
- # Update the proxies if specified.
- for proxyId in removeProxies:
- proxy = self.getResourceById(request, proxyId)
- yield action_removeProxyPrincipal(
- self.root, self.directory, self.store,
- principal, proxy, proxyTypes=["read", "write"]
- )
-
- for proxyId in makeReadProxies:
- proxy = self.getResourceById(request, proxyId)
- yield action_addProxyPrincipal(
- self.root, self.directory, self.store, principal, "read", proxy
- )
-
- for proxyId in makeWriteProxies:
- proxy = self.getResourceById(request, proxyId)
- yield action_addProxyPrincipal(
- self.root, self.directory, self.store, principal,
- "write", proxy
- )
-
-
-
- @inlineCallbacks
- def render(self, request):
- """
- Create a L{WebAdminPage} to render HTML content for this request, and
- return a response.
- """
- resourceId = request.args.get('resourceId', [''])[0]
- if resourceId:
- principal = self.getResourceById(request, resourceId)
- yield self.resourceActions(request, principal)
- htmlContent = yield flattenString(request, WebAdminPage(self))
- response = Response()
- response.stream = MemoryStream(htmlContent)
- for (header, value) in (
- ("content-type", self.contentType()),
- ("content-encoding", self.contentEncoding()),
- ):
- if value is not None:
- response.headers.setHeader(header, value)
- returnValue(response)
-
-
- def getResourceById(self, request, resourceId):
- if resourceId.startswith("/"):
- return request.locateResource(resourceId)
- else:
- return principalForPrincipalID(
- resourceId, directory=self.directory
- )
-
-
- @inlineCallbacks
- def search(self, searchStr):
- records = list((
- yield self.directory.recordsMatchingTokens(
- searchStr.strip().split()
- )
- ))
- returnValue(records)
-
-
-
-
class PageElement(Element):
"""
Page element.
Deleted: CalendarServer/trunk/calendarserver/webadmin/template.html
===================================================================
--- CalendarServer/trunk/calendarserver/webadmin/template.html 2014-03-07 23:09:08 UTC (rev 12852)
+++ CalendarServer/trunk/calendarserver/webadmin/template.html 2014-03-08 00:08:43 UTC (rev 12853)
@@ -1,247 +0,0 @@
-<html xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1"
- t:render="main">
- <head>
- <style>
- th, .even td, .odd td {
- padding-right: 0.5em;
- font-family: monospace;
- }
- .even-dir {
- background-color: #efe0ef;
- }
- .even {
- background-color: #eee;
- }
- .odd-dir {
- background-color: #f0d0ef;
- }
- .odd {
- background-color: #dedede;
- }
- .icon {
- text-align: center;
- }
- .listing {
- margin-left: auto;
- margin-right: auto;
- width: 50%;
- padding: 0.1em;
- }
- .content {
- padding-left: 10px;
- padding-right: 10px;
- }
- body {
- border: 0;
- padding: 0;
- margin: 0;
- background-color: #efefef;
- }
- h1 {
- padding: 0.1em;
- padding-left:10px;
- padding-right:10px;
- background-color: #777;
- color: white;
- border-bottom: thin white dashed;
- }
- </style>
- <title>Calendar Server Web Administration</title>
- </head>
- <body>
- <h1>Calendar Server Web Administration</h1>
- <div class="content">
- <h2>Resource Management</h2>
- <form id="frm_resource" name="resourceForm">
- Search for resource to manage:
- <input type="text" id="txt_resourceSearch" name="resourceSearch"
- size="40"><t:attr name="value"><t:slot name="resourceSearch"
- /></t:attr></input>
- <input type="submit" value="Search" />
- </form>
- <div t:render="noSearchResults" style="margin-top:4px"
- >No matches found for resource <b><t:slot name="resourceSearch" /></b>.
- </div>
- <table id="tab_searchResults" t:render="hasSearchResults" cellspacing="0"
- cellpadding="3" border="1" style="margin-top: 2px">
- <tr class="odd">
- <th>ID</th>
- <th>Full Name</th>
- <th>Type</th>
- <th>Short Names</th>
- <th>Auth IDs</th>
- <th>Email Addresses</th>
- </tr>
- <tr t:render="searchResults">
- <t:attr name="class"><t:slot name="rowClass" /></t:attr>
- <td><a>select<t:attr name="href" >/admin/old/?resourceId=<t:slot
- name="type" />:<t:slot name="shortName" /></t:attr></a></td>
- <td><t:slot name="name" /></td>
- <td><t:slot name="typeStr" /></td>
- <td><t:slot name="shortNames" /></td>
- <td><t:slot name="authIds" /></td>
- <td><t:slot name="emails" /></td>
- </tr>
- </table>
- <div style="margin-top:15px; background-color: #777;
- border-bottom:1px #ffffff dotted"></div>
- <div style="background-color: #777; padding-top:2px;
- border-bottom:1px #ffffff dotted"></div>
-
- <t:transparent t:render="resourceDetails">
- <h3>Resource Details: <t:slot name="resourceTitle" /></h3>
-
- <!-- propertyHTML -->
- <div style="margin-top:15px; border-bottom:1px #444444 dotted"></div>
- <form id="frm_davProperty" name="davPropertyForm" action="/admin/"
- style="margin-top:15px; margin-bottom:0; padding-bottom:0">
- Show a DAV property value:
- <input type="hidden" id="hdn_resourceId" name="resourceId"><t:attr
- name="value"><t:slot name="resourceId" /></t:attr></input>
- <input type="text" id="txt_davPropertyName" name="davPropertyName"
- size="40"><t:attr name="value"><t:slot name="davPropertyName"
- /></t:attr></input>
- <input type="submit" value="Get Value" />
- </form>
-
- <div t:render="propertyParseError">
- Unable to parse property to read: <b><t:slot name="davPropertyName" /></b>
- </div>
-
- <t:transparent t:render="davProperty">
- <div style="margin-top: 7px">Value of property
- <b><t:slot name="davPropertyName" /></b>:</div>
- <pre style="margin-top:5px; padding-top:0"><t:slot name="value" /></pre>
- </t:transparent>
-
- <!-- autoScheduleHtml -->
-
- <t:transparent t:render="autoSchedule">
- <div style="margin-top:15px; border-bottom:1px #444444 dotted"></div>
- <form id="frm_autoSchedule" name="autoScheduleForm" action="/admin/"
- style="margin-top:15px">
- <input type="hidden" id="hdn_resourceId" name="resourceId"
- ><t:attr name="value"><t:slot name="resourceId" /></t:attr></input>
- <div style="margin-top:7px">
- Auto-Schedule
- <select id="sel_autoSchedule" name="autoSchedule">
- <option t:render="isAutoSchedule" value="true">Yes</option>
- <option t:render="isntAutoSchedule" value="false">No</option>
- </select>
- <br/>
- Auto-Schedule Mode
- <select id="sel_autoScheduleMode" name="autoScheduleMode">
- <option t:render="autoScheduleModeDefault" value="default">Default</option>
- <option t:render="autoScheduleModeNone" value="none">None</option>
- <option t:render="autoScheduleModeAcceptAlways" value="accept-always">Accept Always</option>
- <option t:render="autoScheduleModeDeclineAlways" value="decline-always">Decline Always</option>
- <option t:render="autoScheduleModeAcceptIfFree" value="accept-if-free">Accept If Free</option>
- <option t:render="autoScheduleModeDeclineIfBusy" value="decline-if-busy">Decline If Busy</option>
- <option t:render="autoScheduleModeAutomatic" value="automatic">Automatic (Accept and Decline)</option>
- </select>
- <br/>
- <input type="submit" value="Change" />
- </div>
- </form>
- </t:transparent>
-
- <!-- currentProxiesHtml -->
- <div style="margin-top:15px; border-bottom:1px #444444 dotted"></div>
- <form id="frm_proxies" name="proxiesForm" action="/admin/"
- style="margin-top:15px">
- <input type="hidden" id="hdn_resourceId" name="resourceId"
- ><t:attr name="value"><t:slot name="resourceId" /></t:attr></input>
- <div t:render="noProxies" style="margin-top:15px"
- >This resource has no proxies.</div>
- <table cellspacing="0" cellpadding="3" border="1"
- t:render="hasProxies">
- <tr class="odd">
- <th colspan="2">Read-Only Proxies</th>
- <th colspan="2">Read-Write Proxies</th>
- </tr>
- <tr t:render="proxyRows">
- <t:attr name="class"><t:slot name="rowClass" /> </t:attr>
- <t:transparent t:render="readOnlyProxies">
- <td><t:slot name="proxy" /></td>
- <td>
- <input type="submit" value="Make Read-Write"><t:attr
- name="name">mkWriteProxy|<t:slot name="type" />:<t:slot
- name="shortName"/></t:attr></input>
- <input type="submit" value="Remove Proxy"><t:attr
- name="name">rmProxy|<t:slot name="type" />:<t:slot
- name="shortName"/></t:attr></input>
- </td>
- </t:transparent>
-
- <t:transparent t:render="noReadOnlyProxies">
- <td colspan="2"></td>
- </t:transparent>
- <t:transparent t:render="readWriteProxies">
- <td><t:slot name="proxy" /></td>
- <td>
- <input type="submit" value="Make Read-Only"><t:attr
- name="name">mkReadProxy|<t:slot name="type" />:<t:slot
- name="shortName"/></t:attr></input>
- <input type="submit" value="Remove Proxy"><t:attr
- name="name">rmProxy|<t:slot name="type" />:<t:slot
- name="shortName"/></t:attr></input>
- </td>
- </t:transparent>
- <t:transparent t:render="noReadWriteProxies">
- <td colspan="2"></td>
- </t:transparent>
- </tr>
- </table>
- </form>
-
- <!-- proxySearchHtml -->
-
- <div style="margin-top:15px; border-bottom:1px #444444 dotted"></div>
- <div t:render="noProxyResults"
- style="margin-top:4px"
- >No matches found for proxy resource <b><t:slot
- name="proxySearch" /></b>.</div>
- <form id="frm_proxySearch" name="proxySearchForm" action="/admin/"
- style="margin-top:15px; margin-bottom:0; padding-bottom:0">
- Search to add proxies:
- <input type="hidden" id="hdn_resourceId" name="resourceId"
- ><t:attr name="value"><t:slot name="resourceId" /></t:attr></input>
- <input type="text" id="txt_proxySearch" name="proxySearch" size="40"
- ><t:attr name="value"><t:slot name="proxySearch" /></t:attr></input>
- <input type="submit" value="Search"></input>
- </form>
- <form t:render="hasProxyResults"
- id="frm_proxyAdd" name="proxyAddForm" action="/admin/"
- style="margin-top:2px; padding-top:0">
- <input type="hidden" id="hdn_resourceId" name="resourceId"
- ><t:attr name="value"><t:slot name="resourceId" /></t:attr></input>
- <table cellspacing="0" cellpadding="3" border="1">
- <tr class="odd">
- <th>Full Name</th>
- <th>Type</th>
- <th>Short Names</th>
- <th>Email Addresses</th>
- <th></th>
- </tr>
- <tr t:render="proxySearchRows">
- <t:attr name="class"><t:slot name="rowClass" /> </t:attr>
- <td><t:slot name="name" /></td>
- <td><t:slot name="typeStr" /></td>
- <td><t:slot name="shortNames" /></td>
- <td><t:slot name="emails" /></td>
- <td>
- <input type="submit" value="Make Read-Only Proxy"><t:attr
- name="name">mkReadProxy|<t:slot name="type" />:<t:slot
- name="shortName"/></t:attr></input>
- <input type="submit" value="Make Read-Write Proxy"><t:attr
- name="name">mkWriteProxy|<t:slot name="type" />:<t:slot
- name="shortName"/></t:attr></input>
- </td>
- </tr>
- </table>
- </form>
- </t:transparent>
- </div>
-
- </body>
-</html>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140307/3db055b2/attachment-0001.html>
More information about the calendarserver-changes
mailing list