Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Views: 39551
1
##############################################################################
2
#
3
# CoCalc: Collaborative Calculation in the Cloud
4
#
5
# Copyright (C) 2016 -- 2017, 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
{isMobile} = require('./feature')
23
24
{React, ReactDOM, rclass, redux, rtypes, Redux} = require('./smc-react')
25
26
{Navbar, Nav, NavItem} = require('react-bootstrap')
27
{Loading, Icon, Tip} = require('./r_misc')
28
{COLORS} = require('smc-util/theme')
29
30
# CoCalc Pages
31
# SMELL: Page UI's are mixed with their store/state.
32
# So we have to require them even though they aren't used
33
{HelpPage} = require('./r_help')
34
{ProjectsPage} = require('./projects')
35
{ProjectPage} = require('./project_page')
36
{AccountPage} = require('./account_page') # SMELL: Not used but gets around a webpack error..
37
{FileUsePage} = require('./file_use')
38
{Support} = require('./support')
39
40
# CoCalc Libraries
41
misc = require('smc-util/misc')
42
43
{ProjectsNav} = require('./projects_nav')
44
{ActiveAppContent, CookieWarning, GlobalInformationMessage, LocalStorageWarning, ConnectionIndicator, ConnectionInfo, FullscreenButton, NavTab, NotificationBell, AppLogo, VersionWarning} = require('./app_shared')
45
46
FileUsePageWrapper = (props) ->
47
styles =
48
zIndex : '10'
49
marginLeft : '0'
50
position : 'fixed'
51
boxShadow : '0 0 15px #aaa'
52
border : '2px solid #ccc'
53
top : '43px'
54
background : '#fff'
55
right : '2em'
56
overflowY : 'auto'
57
overflowX : 'hidden'
58
fontSize : '10pt'
59
padding : '4px'
60
borderRadius : '5px'
61
width : '50%'
62
height : '90%'
63
64
<div style={styles}>
65
{<FileUsePage redux={redux} />}
66
</div>
67
68
Page = rclass
69
displayName : "Page"
70
71
reduxProps :
72
projects :
73
open_projects : rtypes.immutable.List
74
page :
75
active_top_tab : rtypes.string # key of the active tab
76
show_connection : rtypes.bool
77
ping : rtypes.number
78
avgping : rtypes.number
79
connection_status : rtypes.string
80
new_version : rtypes.object
81
fullscreen : rtypes.oneOf(['default', 'kiosk'])
82
cookie_warning : rtypes.bool
83
local_storage_warning : rtypes.bool
84
show_file_use : rtypes.bool
85
file_use :
86
file_use : rtypes.immutable.Map
87
get_notify_count : rtypes.func
88
account :
89
first_name : rtypes.string # Necessary for get_fullname
90
last_name : rtypes.string # Necessary for get_fullname
91
get_fullname : rtypes.func
92
user_type : rtypes.string # Necessary for is_logged_in
93
is_logged_in : rtypes.func
94
other_settings : rtypes.object
95
is_global_info_visible : rtypes.func
96
support :
97
show : rtypes.bool
98
99
propTypes :
100
redux : rtypes.object
101
102
componentWillUnmount: ->
103
@actions('page').clear_all_handlers()
104
105
account_name: ->
106
name = ''
107
if @props.get_fullname?
108
name = misc.trunc_middle(@props.get_fullname(), 32)
109
if not name.trim()
110
name = "Account"
111
112
return name
113
114
render_account_tab: ->
115
<NavTab
116
name = 'account'
117
label = {@account_name()}
118
icon = 'cog'
119
actions = {@actions('page')}
120
active_top_tab = {@props.active_top_tab}
121
/>
122
123
sign_in_tab_clicked: ->
124
if @props.active_top_tab == 'account'
125
@actions('page').sign_in()
126
127
render_sign_in_tab: ->
128
<NavTab
129
name = 'account'
130
label = 'Sign in'
131
icon = 'sign-in'
132
on_click = {@sign_in_tab_clicked}
133
actions = {@actions('page')}
134
active_top_tab = {@props.active_top_tab}
135
style = {backgroundColor:COLORS.TOP_BAR.SIGN_IN_BG}
136
add_inner_style = {color: 'black'}
137
/>
138
139
render_right_nav: ->
140
logged_in = @props.is_logged_in()
141
<Nav id='smc-right-tabs-fixed' style={height:'40px', lineHeight:'20px', margin:'0', overflowY:'hidden'}>
142
{@render_account_tab() if logged_in}
143
{@render_sign_in_tab() if not logged_in}
144
<NavTab name='about' label='About' icon='question-circle' actions={@actions('page')} active_top_tab={@props.active_top_tab} />
145
<NavItem className='divider-vertical hidden-xs' />
146
{<NavTab
147
label='Help' icon='medkit'
148
actions={@actions('page')}
149
active_top_tab={@props.active_top_tab}
150
on_click={=>redux.getActions('support').show(true)}
151
/> if require('./customize').commercial}
152
{<NotificationBell count={@props.get_notify_count()} active={@props.show_file_use} /> if @props.is_logged_in()}
153
<ConnectionIndicator actions={@actions('page')} />
154
</Nav>
155
156
render_project_nav_button: ->
157
projects_styles =
158
whiteSpace : 'nowrap'
159
float : 'right'
160
padding : '11px 7px'
161
fontWeight : 'bold'
162
163
<Nav style={height:'40px', margin:'0', overflow:'hidden'}>
164
<NavTab
165
name = 'projects'
166
inner_style = {padding:'0px'}
167
actions = {@actions('page')}
168
active_top_tab = {@props.active_top_tab}
169
170
>
171
<div style={projects_styles}>
172
Projects
173
</div>
174
<AppLogo />
175
</NavTab>
176
</Nav>
177
178
# register a default drag and drop handler, that prevents accidental file drops
179
# TEST: make sure that usual drag'n'drop activities like rearranging tabs and reordering tasks work
180
drop: (e) ->
181
if DEBUG
182
e.persist()
183
console.log "react desktop_app.drop", e
184
e.preventDefault()
185
e.stopPropagation()
186
if e.dataTransfer.files.length > 0
187
{alert_message} = require('./alerts')
188
alert_message
189
type : 'info'
190
title : 'File Drop Rejected'
191
message : 'To upload a file, drop it onto the files listing or the "Drop files to upload" area in the +New tab.'
192
193
render: ->
194
style =
195
display : 'flex'
196
flexDirection : 'column'
197
height : '100vh'
198
width : '100vw'
199
overflow : 'hidden'
200
201
show_global_info = @props.is_global_info_visible() and (not @props.fullscreen) and @props.is_logged_in()
202
203
style_top_bar =
204
display : 'flex'
205
marginBottom : 0
206
width : '100%'
207
minHeight : '40px'
208
position : 'fixed'
209
right : 0
210
zIndex : '100'
211
borderRadius : 0
212
top : if show_global_info then '40px' else 0
213
214
positionHackHeight = (40 + if show_global_info then 40 else 0) + 'px'
215
216
<div ref="page" style={style} onDragOver={(e) -> e.preventDefault()} onDrop={@drop}>
217
{<FileUsePageWrapper /> if @props.show_file_use}
218
{<ConnectionInfo ping={@props.ping} status={@props.connection_status} avgping={@props.avgping} actions={@actions('page')} /> if @props.show_connection}
219
{<Support actions={@actions('support')} /> if @props.show}
220
{<VersionWarning new_version={@props.new_version} /> if @props.new_version?}
221
{<CookieWarning /> if @props.cookie_warning}
222
{<LocalStorageWarning /> if @props.local_storage_warning}
223
{<GlobalInformationMessage /> if show_global_info}
224
{<Navbar className="smc-top-bar" style={style_top_bar}>
225
{@render_project_nav_button() if @props.is_logged_in()}
226
<ProjectsNav dropdown={false} />
227
{@render_right_nav()}
228
</Navbar> if not @props.fullscreen}
229
{<div className="smc-sticky-position-hack" style={minHeight:positionHackHeight}> </div>if not @props.fullscreen}
230
{<FullscreenButton /> if (@props.fullscreen != 'kiosk')}
231
{# Children must define their own padding from navbar and screen borders}
232
{# Note that the parent is a flex container}
233
<ActiveAppContent active_top_tab={@props.active_top_tab}/>
234
</div>
235
236
page = <Redux redux={redux}>
237
<Page redux={redux}/>
238
</Redux>
239
240
exports.render = () => ReactDOM.render(page, document.getElementById('smc-react-container'))
241