mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-01-19 11:16:24 +00:00
WUI: change the label of the button to unlink a file from 'del' to 'unlink'. Also change some internal names to 'unlink', and allow 't=unlink' as a synonym for 't=delete' in the web-API interface. Incidentally, improve a test to check for the rename button as well as the unlink button. fixes #1104
This commit is contained in:
parent
23b3a2f45a
commit
07ecac1d83
@ -88,7 +88,7 @@ URL) will return information about the object, such as metadata. GET
|
||||
operations are required to have no side-effects.
|
||||
|
||||
PUT is used to upload new objects into the filesystem, or to replace an
|
||||
existing object. DELETE it used to delete objects from the filesystem. Both
|
||||
existing object. DELETE is used to delete objects from the filesystem. Both
|
||||
PUT and DELETE are required to be idempotent: performing the same operation
|
||||
multiple times must have the same side-effects as only performing it once.
|
||||
|
||||
@ -1159,6 +1159,11 @@ Deleting A Child
|
||||
into the subtree will see that the child subdirectories are not modified by
|
||||
this operation. Only the link from the given directory to its child is severed.
|
||||
|
||||
In Tahoe-LAFS v1.9.0 and later, t=unlink can be used as a synonym for t=delete.
|
||||
If interoperability with older web-API servers is required, t=delete should
|
||||
be used.
|
||||
|
||||
|
||||
Renaming A Child
|
||||
----------------
|
||||
|
||||
|
@ -1093,21 +1093,25 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
|
||||
r'\s+<td align="right">%d</td>' % len(self.BAR_CONTENTS),
|
||||
])
|
||||
self.failUnless(re.search(get_bar, res), res)
|
||||
for label in ['unlink', 'rename']:
|
||||
for line in res.split("\n"):
|
||||
# find the line that contains the delete button for bar.txt
|
||||
# find the line that contains the relevant button for bar.txt
|
||||
if ("form action" in line and
|
||||
'value="delete"' in line and
|
||||
('value="%s"' % (label,)) in line and
|
||||
'value="bar.txt"' in line):
|
||||
# the form target should use a relative URL
|
||||
foo_url = urllib.quote("%s/uri/%s/" % (ROOT, self._foo_uri))
|
||||
self.failUnless(('action="%s"' % foo_url) in line, line)
|
||||
self.failUnlessIn('action="%s"' % foo_url, line)
|
||||
# and the when_done= should too
|
||||
#done_url = urllib.quote(???)
|
||||
#self.failUnless(('name="when_done" value="%s"' % done_url)
|
||||
# in line, line)
|
||||
#self.failUnlessIn('name="when_done" value="%s"' % done_url, line)
|
||||
|
||||
# 'unlink' needs to use POST because it directly has a side effect
|
||||
if label == 'unlink':
|
||||
self.failUnlessIn('method="post"', line)
|
||||
break
|
||||
else:
|
||||
self.fail("unable to find delete-bar.txt line", res)
|
||||
self.fail("unable to find '%s bar.txt' line" % (label,), res)
|
||||
|
||||
# the DIR reference just points to a URI
|
||||
sub_url = ("%s/uri/%s/" % (ROOT, urllib.quote(self._sub_uri)))
|
||||
@ -2638,14 +2642,21 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
|
||||
d.addCallback(self.failUnlessIsBarDotTxt)
|
||||
return d
|
||||
|
||||
def test_POST_delete(self):
|
||||
d = self.POST(self.public_url + "/foo", t="delete", name="bar.txt")
|
||||
def test_POST_delete(self, command_name='delete'):
|
||||
d = self._foo_node.list()
|
||||
def _check_before(children):
|
||||
self.failUnless(u"bar.txt" in children)
|
||||
d.addCallback(_check_before)
|
||||
d.addCallback(lambda res: self.POST(self.public_url + "/foo", t=command_name, name="bar.txt"))
|
||||
d.addCallback(lambda res: self._foo_node.list())
|
||||
def _check(children):
|
||||
def _check_after(children):
|
||||
self.failIf(u"bar.txt" in children)
|
||||
d.addCallback(_check)
|
||||
d.addCallback(_check_after)
|
||||
return d
|
||||
|
||||
def test_POST_unlink(self):
|
||||
return self.test_POST_delete(command_name='unlink')
|
||||
|
||||
def test_POST_rename_file(self):
|
||||
d = self.POST(self.public_url + "/foo", t="rename",
|
||||
from_name="bar.txt", to_name='wibble.txt')
|
||||
|
@ -202,8 +202,8 @@ class DirectoryNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
|
||||
d = self._POST_upload(ctx) # this one needs the context
|
||||
elif t == "uri":
|
||||
d = self._POST_uri(req)
|
||||
elif t == "delete":
|
||||
d = self._POST_delete(req)
|
||||
elif t == "delete" or t == "unlink":
|
||||
d = self._POST_unlink(req)
|
||||
elif t == "rename":
|
||||
d = self._POST_rename(req)
|
||||
elif t == "check":
|
||||
@ -361,22 +361,22 @@ class DirectoryNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
|
||||
d.addCallback(lambda res: childcap)
|
||||
return d
|
||||
|
||||
def _POST_delete(self, req):
|
||||
def _POST_unlink(self, req):
|
||||
name = get_arg(req, "name")
|
||||
if name is None:
|
||||
# apparently an <input type="hidden" name="name" value="">
|
||||
# won't show up in the resulting encoded form.. the 'name'
|
||||
# field is completely missing. So to allow deletion of an
|
||||
# empty file, we have to pretend that None means ''. The only
|
||||
# downside of this is a slightly confusing error message if
|
||||
# someone does a POST without a name= field. For our own HTML
|
||||
# this isn't a big deal, because we create the 'delete' POST
|
||||
# buttons ourselves.
|
||||
# field is completely missing. So to allow unlinking of a
|
||||
# child with a name that is the empty string, we have to
|
||||
# pretend that None means ''. The only downside of this is
|
||||
# a slightly confusing error message if someone does a POST
|
||||
# without a name= field. For our own HTML this isn't a big
|
||||
# deal, because we create the 'unlink' POST buttons ourselves.
|
||||
name = ''
|
||||
charset = get_arg(req, "_charset", "utf-8")
|
||||
name = name.decode(charset)
|
||||
d = self.node.delete(name)
|
||||
d.addCallback(lambda res: "thing deleted")
|
||||
d.addCallback(lambda res: "thing unlinked")
|
||||
return d
|
||||
|
||||
def _POST_rename(self, req):
|
||||
@ -644,17 +644,17 @@ class DirectoryAsHTML(rend.Page):
|
||||
root = get_root(ctx)
|
||||
here = "%s/uri/%s/" % (root, urllib.quote(self.node.get_uri()))
|
||||
if self.node.is_unknown() or self.node.is_readonly():
|
||||
delete = "-"
|
||||
unlink = "-"
|
||||
rename = "-"
|
||||
else:
|
||||
# this creates a button which will cause our child__delete method
|
||||
# to be invoked, which deletes the file and then redirects the
|
||||
# this creates a button which will cause our _POST_unlink method
|
||||
# to be invoked, which unlinks the file and then redirects the
|
||||
# browser back to this directory
|
||||
delete = T.form(action=here, method="post")[
|
||||
T.input(type='hidden', name='t', value='delete'),
|
||||
unlink = T.form(action=here, method="post")[
|
||||
T.input(type='hidden', name='t', value='unlink'),
|
||||
T.input(type='hidden', name='name', value=name),
|
||||
T.input(type='hidden', name='when_done', value="."),
|
||||
T.input(type='submit', value='del', name="del"),
|
||||
T.input(type='submit', value='unlink', name="unlink"),
|
||||
]
|
||||
|
||||
rename = T.form(action=here, method="get")[
|
||||
@ -664,7 +664,7 @@ class DirectoryAsHTML(rend.Page):
|
||||
T.input(type='submit', value='rename', name="rename"),
|
||||
]
|
||||
|
||||
ctx.fillSlots("delete", delete)
|
||||
ctx.fillSlots("unlink", unlink)
|
||||
ctx.fillSlots("rename", rename)
|
||||
|
||||
times = []
|
||||
|
@ -31,7 +31,7 @@
|
||||
<td><n:slot name="filename"/></td>
|
||||
<td align="right"><n:slot name="size"/></td>
|
||||
<td><n:slot name="times"/></td>
|
||||
<td><n:slot name="delete"/></td>
|
||||
<td><n:slot name="unlink"/></td>
|
||||
<td><n:slot name="rename"/></td>
|
||||
<td><n:slot name="info"/></td>
|
||||
</tr>
|
||||
|
Loading…
Reference in New Issue
Block a user