Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Views: 39550
1
###############################################################################
2
#
3
# CoCalc: Collaborative Calculation in the Cloud
4
#
5
# Copyright (C) 2015, SageMath, Inc.
6
#
7
# This program is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
#
20
###############################################################################
21
22
{alert_message} = require('./alerts')
23
{webapp_client} = require('./webapp_client')
24
25
# load dependencies asynchronously
26
exports.load = (element, project) ->
27
# FUTURE: use require to load these if we decide to go with react.
28
jQuery.getScript 'https://fb.me/react-0.13.3.min.js', ->
29
jQuery.getScript 'https://cdnjs.cloudflare.com/ajax/libs/dropbox.js/0.10.2/dropbox.min.js', ->
30
DropboxFolderSelector = React.createClass
31
getInitialState: ->
32
{ # SMELL: probably don't need these braces.
33
selected: null
34
new_folder: "something"
35
}
36
37
click: (folder) ->
38
=>
39
@props.setFolderSelection(folder)
40
41
newFolder: ->
42
@props.newFolder(@state.new_folder)
43
44
onNewFolderChange: (event) ->
45
@setState { new_folder: event.target.value }
46
47
render: ->
48
folders = @props.folders.map (folder) => <li onClick={@click(folder)} className="list-group-item">{folder}</li>
49
50
<div>
51
<div>
52
<form>
53
<div className="form-group">
54
<label>Create a new folder in your Dropbox account to sync to your project</label>
55
<input onChange={@onNewFolderChange} className="form-control" type="text" name="new-folder" value={@state.new_folder} />
56
</div>
57
<button type="button" className="btn btn-default" onClick={@newFolder}>Create</button>
58
</form>
59
</div>
60
<hr />
61
<div>
62
<p>Or, please select a folder from <tt>{@props.folderPath}</tt></p>
63
<ul className="list-group">
64
{folders}
65
</ul>
66
</div>
67
</div>
68
69
DropboxButton = React.createClass
70
authorize: ->
71
# The key below is the Dropbox public key that you register with Dropbox to get.
72
# FUTURE: replace with wstein's key
73
client = new Dropbox.Client({ key: '4nkctd7tebtf3o9' })
74
client.authDriver(new Dropbox.AuthDriver.Popup({
75
receiverUrl: "https://dev.sagemath.com/static/dropbox_oauth_receiver.html"}))
76
client.authenticate (error, client) =>
77
if error
78
console.log(error)
79
return
80
@props.setClient(client)
81
render: ->
82
<div className="smc-dropbox-area">
83
<button onClick={@authorize} className="btn btn-default btn-lg">Authorize with Dropbox</button>
84
</div>
85
86
DropboxSection = React.createClass
87
getInitialState: ->
88
{
89
client: null
90
authorized: false
91
folders: []
92
folderPath: null
93
processing: false
94
}
95
readFolder: (path) ->
96
@state.client.readdir path, null, (error, files, stat, stats) =>
97
folders = stats.filter((entry) -> entry.isFolder).map((entry) -> entry.path)
98
@setState { folderPath: path, folders: folders }
99
setClient: (client) ->
100
@setState { client: client, authorized: true }, ->
101
@readFolder('/')
102
setFolderSelection: (path) ->
103
# we're done... so send this to the backend
104
console.log("Sending folder", path, "to backend")
105
@setState { processing: true }
106
webapp_client.update_project_data
107
project_id : project.project_id
108
data : {dropbox_folder: path, dropbox_token: @state.client.credentials().token}
109
cb : (err, mesg) ->
110
if err
111
alert_message(type:'error', message:"Error contacting server to save dropbox settings.")
112
else if mesg.event == "error"
113
alert_message(type:'error', message:mesg.error)
114
else
115
# success!
116
# ....
117
alert("okay")
118
119
newFolder: (folder) ->
120
@setState { processing: true }
121
console.log("Creating new folder", folder)
122
path = @state.folderPath + '/' + folder
123
@state.client.mkdir path, (error, stat) =>
124
if error
125
alert(error)
126
return
127
@setFolderSelection(path)
128
render: ->
129
if @state.processing
130
<div>Processing <span className="fa fa-spin fa-refresh" /></div>
131
else if @state.authorized
132
<DropboxFolderSelector client={@state.client} folders={@state.folders} folderPath={@state.folderPath}
133
setFolderPath={@readFolder} setFolderSelection={@setFolderSelection} newFolder={@newFolder} />
134
else
135
<DropboxButton setClient={@setClient} />
136
137
ReactDOM.render(<DropboxSection />, element)
138
139
140