~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to ivle/webapp/filesystem/browser/__init__.py

Merged from new-dispatch branch.
This branch is now a child of new-dispatch (until that branch is merged with
    trunk).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# IVLE
2
 
# Copyright (C) 2007-2008 The University of Melbourne
 
1
# IVLE - Informatics Virtual Learning Environment
 
2
# Copyright (C) 2007-2009 The University of Melbourne
3
3
#
4
4
# This program is free software; you can redistribute it and/or modify
5
5
# it under the terms of the GNU General Public License as published by
15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
17
 
18
 
# App: File Browser
19
 
# Author: Matt Giuca
20
 
# Date: 9/1/2008
21
 
 
22
 
# The file browser application. Presents an Ajax-based interface to the
23
 
# student's subversion workspace.
24
 
# Note that there is virtually no server-side code for this application. It
25
 
# simply presents static HTML and JavaScript, and all server-side activities
26
 
# take place in the FileService app (for handling Ajax requests).
 
18
# Author: Matt Giuca, Nick Chadwick
 
19
 
 
20
"""
 
21
The file browser application. Presents an Ajax-based interface to the
 
22
student's subversion workspace.
 
23
 
 
24
Note that there is virtually no server-side code for this application. It
 
25
simply presents static HTML and JavaScript, and all server-side activities
 
26
take place in the FileService app (for handling Ajax requests).
 
27
"""
 
28
 
 
29
from ivle.webapp.base.plugins import ViewPlugin, CookiePlugin, MediaPlugin
 
30
from ivle.webapp.base.xhtml import XHTMLView
27
31
 
28
32
import os.path
29
33
import cgi
31
35
from ivle import (util, studpath)
32
36
import ivle.svn
33
37
 
34
 
import genshi
35
 
import genshi.core
36
 
import genshi.template
37
 
 
38
 
# url path for this app
39
 
THIS_APP = "files"
40
 
 
41
 
def handle(req):
42
 
    """Handler for the File Browser application."""
43
 
 
44
 
    # Work out where we are browsing
45
 
    browsepath = req.path
46
 
    if len(browsepath) == 0:
47
 
        # If no path specified, default to the user's home directory
48
 
        redirectPath = util.make_path(os.path.join(THIS_APP,req.user.login))
49
 
        req.throw_redirect(util.make_path(redirectPath))
50
 
 
51
 
    ctx = genshi.template.Context()
52
 
 
53
 
    # Set request attributes
54
 
    req.content_type = "text/html"
55
 
    req.styles = [
56
 
        "media/browser/browser.css",
57
 
        "media/browser/listing.css",
58
 
        "media/browser/editor.css",
59
 
    ]
60
 
    req.scripts = [
61
 
        "media/common/json2.js",
62
 
        "media/common/codepress/codepress.js",
63
 
        "media/common/util.js",
64
 
        "media/browser/browser.js",
65
 
        "media/browser/listing.js",
66
 
        "media/browser/editor.js",
67
 
        "media/browser/specialhome.js",
68
 
    ]
69
 
    req.scripts_init = [
70
 
        "browser_init",
71
 
    ]
72
 
 
73
 
    req.write_html_head_foot = True     # Have dispatch print head and foot
74
 
    # The page title should contain the name of the file being browsed
75
 
    req.title = browsepath.rsplit('/', 1)[-1]
76
 
 
77
 
    _, localpath = studpath.url_to_local(browsepath)
78
 
    if localpath is None:
79
 
        req.throw_error(req.HTTP_NOT_FOUND,
80
 
            "The path specified is invalid.")
81
 
 
82
 
    # Start writing data
83
 
 
84
 
    # FIXME: This isn't completely reliable! We're not inside the jail, so we
85
 
    # can't know the type for sure. This is now only used for adding a / to the
86
 
    # end of displayed paths, so I'm leaving this although it will often break.
87
 
    isdir = os.path.isdir(localpath)
88
 
    ctx['isdir'] = isdir
89
 
    gen_path(req, browsepath, ctx)
90
 
    gen_actions(req, ctx)
91
 
    
92
 
    ctx['fileservice_action'] = util.make_path(os.path.join("fileservice", req.path))
93
 
    ctx['filename'] = cgi.escape(req.path)
94
 
 
95
 
    loader = genshi.template.TemplateLoader(".", auto_reload=True)
96
 
    tmpl = loader.load(util.make_local_path("apps/browser/template.html"))
97
 
    
98
 
    req.write(tmpl.generate(ctx).render('html')) #'xhtml', doctype='xhtml'))
99
 
 
100
 
#TODO: Move all this logic into the template
101
 
def gen_path(req, path, ctx):
102
 
 
103
 
    href_path = util.make_path(THIS_APP)
104
 
    nav_path = ""
105
 
    revision = ivle.svn.revision_from_string(
106
 
                     req.get_fieldstorage().getfirst('r'))
107
 
    try: 
108
 
        revno = revision.number
109
 
    except:
110
 
        revno = None
111
 
      
112
 
    ctx['revno'] = revno
113
 
    
114
 
    # Create all of the paths
115
 
    pathlist = path.split("/")
116
 
    ctx['paths'] = []
117
 
    for path_seg in pathlist:
118
 
        if path_seg == "":
119
 
            continue
120
 
        new_seg = {}
121
 
        
122
 
        nav_path = nav_path + path_seg
123
 
        href_path = href_path + '/' + path_seg
124
 
        
125
 
        new_seg['path'] = path_seg        
126
 
        new_seg['nav_path'] = nav_path
127
 
        new_seg['href_path'] = href_path
128
 
        if revno is not None:
129
 
            new_seg['href_path'] += '?r=%d' % revno
130
 
        
131
 
        ctx['paths'].append(new_seg)
132
 
 
133
 
 
134
 
def gen_actions(req, ctx):
135
 
    """
136
 
    Presents a set of links/buttons for the "actions1" row of the top bar.
137
 
    This is always exactly the same - the JavaScript will customize it later.
138
 
    """
139
 
    # Set up our actions. The second field of each group is whether to disable
140
 
    # the items by default.
141
 
    ctx['moreactions'] = [
142
 
      ('Publishing', True, [
143
 
        ('publish', ['Publish',          'Make it so this directory can be seen by anyone on the web']),
144
 
        ('share',   ['Share this file',  'Get a link to this published file, to give to friends']),
145
 
        ('submit',  ['Submit', 'Submit the selected files for an assignment'])
146
 
      ]),
147
 
      ('File actions', True, [
148
 
        ('rename',  ['Rename',           'Change the name of this file']),
149
 
        ('delete',  ['Delete',           'Delete the selected files']),
150
 
        ('copy',    ['Copy',             'Prepare to copy the selected files to another directory']),
151
 
        ('cut',     ['Cut',              'Prepare to move the selected files to another directory'])
152
 
      ]),
153
 
      ('Directory actions', False, [
154
 
        ('paste',   ['Paste',            'Paste the copied or cut files into the current directory']),
155
 
        ('newfile', ['New File',         'Open a new file for editing in the current directory']),
156
 
        ('mkdir',   ['New Directory',    'Make a new subdirectory in the current directory']),
157
 
        ('upload',  ['Upload File',      'Upload a file to the current directory'])
158
 
      ]),
159
 
      ('Subversion', True, [
160
 
        ('svncut',      ['Svn Cut',      'Prepare to move the selected files to another directory, maintaining history']),
161
 
        ('svncopy',     ['Svn Copy',     'Prepare to copy the selected files to another directory, maintaining history']),
162
 
        ('svnadd',      ['Add',            'Schedule the selected temporary files to be added permanently']),
163
 
        ('svnremove',   ['Remove',         'Schedule the selected permanent files to be removed']),
164
 
        ('svndiff',     ['Diff',           'View any changes to the selected file since its last committed state']),
165
 
        ('svnrevert',   ['Revert',         'Restore the selected files back to their last committed state']),
166
 
        ('svnupdate',   ['Update',         'Update your files with changes from the permanent repository']),
167
 
        ('svncommit',   ['Commit',         'Commit any changes to the permanent repository']),
168
 
        ('svnresolved', ['Mark Resolved',  'Mark a conflicted file as being resolved']),
169
 
        ('svnlog',      ['View Log',       'View the log of commits of the selected file']),
170
 
      ])
171
 
    ]
 
38
class BrowserView(XHTMLView):
 
39
    """
 
40
    The view for the browser
 
41
    """
 
42
    template = 'template.html'
 
43
    appname = 'files'
 
44
 
 
45
    def populate(self, req, ctx):
 
46
        if not hasattr(self, 'path'):
 
47
            # If no path specified, default to the user's home directory
 
48
            redirectPath = util.make_path(os.path.join('files', req.user.login))
 
49
            req.throw_redirect(util.make_path(redirectPath))
 
50
 
 
51
        # Set request attributes
 
52
        self.plugin_styles[Plugin] = ['browser.css',
 
53
                                      'listing.css',
 
54
                                      'editor.css']
 
55
        self.plugin_scripts[Plugin] = ['browser.js',
 
56
                                       'listing.js',
 
57
                                       'editor.js',
 
58
                                       'specialhome.js']
 
59
        req.scripts = ["/media/common/codepress/codepress.js"]
 
60
        req.scripts_init = ["browser_init"]
 
61
 
 
62
        # The page title should contain the name of the file being browsed
 
63
        req.title = self.path.rsplit('/', 1)[-1]
 
64
 
 
65
        _, localpath = studpath.url_to_local(self.path)
 
66
        if localpath is None:
 
67
            raise NotFound()
 
68
 
 
69
        # Start writing data
 
70
 
 
71
        # FIXME: This isn't completely reliable! We're not inside the jail, so we
 
72
        # can't know the type for sure. This is now only used for adding a / to the
 
73
        # end of displayed paths, so I'm leaving this although it will often break.
 
74
        isdir = os.path.isdir(localpath)
 
75
        ctx['isdir'] = isdir
 
76
        self.gen_path(req, ctx)
 
77
        self.gen_actions(req, ctx)
 
78
 
 
79
        ctx['fileservice_action'] = util.make_path(os.path.join("fileservice", req.path))
 
80
        ctx['filename'] = cgi.escape(req.path)
 
81
 
 
82
    #TODO: Move all this logic into the template
 
83
    def gen_path(self, req, ctx):
 
84
 
 
85
        href_path = util.make_path('files')
 
86
        nav_path = ""
 
87
        revision = ivle.svn.revision_from_string(
 
88
                         req.get_fieldstorage().getfirst('r'))
 
89
        try:
 
90
            revno = revision.number
 
91
        except:
 
92
            revno = None
 
93
 
 
94
        ctx['revno'] = revno
 
95
 
 
96
        # Create all of the paths
 
97
        pathlist = self.path.split("/")
 
98
        ctx['paths'] = []
 
99
        for path_seg in pathlist:
 
100
            if path_seg == "":
 
101
                continue
 
102
            new_seg = {}
 
103
 
 
104
            nav_path = nav_path + path_seg
 
105
            href_path = href_path + '/' + path_seg
 
106
 
 
107
            new_seg['path'] = path_seg
 
108
            new_seg['nav_path'] = nav_path
 
109
            new_seg['href_path'] = href_path
 
110
            if revno is not None:
 
111
                new_seg['href_path'] += '?r=%d' % revno
 
112
 
 
113
            ctx['paths'].append(new_seg)
 
114
 
 
115
    def gen_actions(self, req, ctx):
 
116
        """
 
117
        Presents a set of links/buttons for the "actions1" row of the top bar.
 
118
        This is always exactly the same - the JavaScript will customize it later.
 
119
        """
 
120
        # Set up our actions. The second field of each group is whether to disable
 
121
        # the items by default.
 
122
        ctx['moreactions'] = [
 
123
          ('Publishing', True, [
 
124
            ('publish', ['Publish',          'Make it so this directory can be seen by anyone on the web']),
 
125
            ('share',   ['Share this file',  'Get a link to this published file, to give to friends']),
 
126
            ('submit',  ['Submit', 'Submit the selected files for an assignment'])
 
127
          ]),
 
128
          ('File actions', True, [
 
129
            ('rename',  ['Rename',           'Change the name of this file']),
 
130
            ('delete',  ['Delete',           'Delete the selected files']),
 
131
            ('copy',    ['Copy',             'Prepare to copy the selected files to another directory']),
 
132
            ('cut',     ['Cut',              'Prepare to move the selected files to another directory'])
 
133
          ]),
 
134
          ('Directory actions', False, [
 
135
            ('paste',   ['Paste',            'Paste the copied or cut files into the current directory']),
 
136
            ('newfile', ['New File',         'Open a new file for editing in the current directory']),
 
137
            ('mkdir',   ['New Directory',    'Make a new subdirectory in the current directory']),
 
138
            ('upload',  ['Upload File',      'Upload a file to the current directory'])
 
139
          ]),
 
140
          ('Subversion', True, [
 
141
            ('svncut',      ['Svn Cut',      'Prepare to move the selected files to another directory, maintaining history']),
 
142
            ('svncopy',     ['Svn Copy',     'Prepare to copy the selected files to another directory, maintaining history']),
 
143
            ('svnadd',      ['Add',            'Schedule the selected temporary files to be added permanently']),
 
144
            ('svnremove',   ['Remove',         'Schedule the selected permanent files to be removed']),
 
145
            ('svndiff',     ['Diff',           'View any changes to the selected file since its last committed state']),
 
146
            ('svnrevert',   ['Revert',         'Restore the selected files back to their last committed state']),
 
147
            ('svnupdate',   ['Update',         'Update your files with changes from the permanent repository']),
 
148
            ('svncommit',   ['Commit',         'Commit any changes to the permanent repository']),
 
149
            ('svnresolved', ['Mark Resolved',  'Mark a conflicted file as being resolved']),
 
150
            ('svnlog',      ['View Log',       'View the log of commits of the selected file']),
 
151
          ])
 
152
        ]
 
153
 
 
154
class Plugin(ViewPlugin, CookiePlugin, MediaPlugin):
 
155
    """
 
156
    The Plugin class for the user plugin.
 
157
    """
 
158
    # Magic attribute: urls
 
159
    # Sequence of pairs/triples of
 
160
    # (regex str, handler class, kwargs dict)
 
161
    # The kwargs dict is passed to the __init__ of the view object
 
162
    urls = [
 
163
        ('files/*(path)', BrowserView),
 
164
        ('files/', BrowserView),
 
165
    ]
 
166
 
 
167
    cookies = {'clipboard': None}
 
168
 
 
169
    media = 'media'