From 056a0ef397179d26523d532ca2afaf02943638cc Mon Sep 17 00:00:00 2001 From: william+nicholas+jon Date: Tue, 1 Sep 2015 01:23:31 +0000 Subject: [PATCH] sharing an entire project --- salvus/page/project_files.cjsx | 61 ++++++------- salvus/page/project_log.cjsx | 2 +- salvus/page/project_settings.cjsx | 142 +++++++++++++++++++++--------- salvus/page/project_store.coffee | 10 ++- 4 files changed, 136 insertions(+), 79 deletions(-) diff --git a/salvus/page/project_files.cjsx b/salvus/page/project_files.cjsx index 48cd9146a4..6c732775d3 100644 --- a/salvus/page/project_files.cjsx +++ b/salvus/page/project_files.cjsx @@ -176,33 +176,24 @@ FileRow = rclass @render_name_link(styles, name, ext) - render_public_file_info_popover : (currently_shared) -> - if currently_shared - - - Description: {@props.public_data.description} - - - else - - - If you want to share this file again, select the checkbox and then click - the ' Share...' button. - - + render_public_file_info_popover : -> + + + Description: {@props.public_data.description} + + render_public_file_info : -> - if @props.public_data? + if @props.public_data? and @props.is_public   + overlay = {@render_public_file_info_popover()} > @@ -264,28 +255,22 @@ DirectoryRow = rclass @props.actions.set_file_search('') @props.actions.set_url_to_path(path) - render_public_directory_info_popover : (currently_shared) -> - if currently_shared - - Description: {@props.public_data.description} - - else - - If you want to share this folder again, click the checkbox and then click 'Share' - + render_public_directory_info_popover : -> + + Description: {@props.public_data.description} + render_public_directory_info : -> - if @props.public_data? + if @props.public_data? and @props.is_public   + overlay = {@render_public_directory_info_popover()} > @@ -378,7 +363,7 @@ FileListing = rclass propTypes : listing : rtypes.array.isRequired - file_map : rtypes.object + file_map : rtypes.object.isRequired checked_files : rtypes.object current_path : rtypes.string page_number : rtypes.number @@ -1020,7 +1005,13 @@ ProjectFilesActionBox = rclass different_project_button : -> - + copy_click : -> destination_directory = @state.copy_destination_directory @@ -1234,7 +1225,9 @@ ProjectFilesActionBox = rclass action = @props.file_action action_button = file_action_buttons[action] if not action_button? -
Undefined action
+ return
Undefined action
+ if not @props.file_map? + return else diff --git a/salvus/page/project_log.cjsx b/salvus/page/project_log.cjsx index ef0903ae65..d2b5b8e663 100644 --- a/salvus/page/project_log.cjsx +++ b/salvus/page/project_log.cjsx @@ -396,7 +396,7 @@ ProjectLog = rclass - + diff --git a/salvus/page/project_settings.cjsx b/salvus/page/project_settings.cjsx index aef7f3e6ef..6119dab495 100644 --- a/salvus/page/project_settings.cjsx +++ b/salvus/page/project_settings.cjsx @@ -386,49 +386,100 @@ UsagePanel = rclass
-ShareCopyPanel = rclass - displayName : 'ProjectSettings-ShareCopyPanel' +SharePanel = rclass + displayName : 'ProjectSettings-SharePanel' propTypes : - project : rtypes.object.isRequired - flux : rtypes.object.isRequired + project : rtypes.object.isRequired + public_paths : rtypes.object.isRequired + flux : rtypes.object.isRequired + desc : rtypes.string.isRequired getInitialState : -> - state : 'view' # view --> edit --> saving --> view - share_desc : @ - - render_share : -> - @setState(description_text:@refs.share_description.getValue())} /> + state : 'view' # view --> edit --> view + desc : @props.desc + + componentWillReceiveProps : (nextProps) -> + if @state.desc isnt nextProps.desc + @setState + desc : nextProps.desc + state : 'view' + + cancel : -> + @setState(state : 'view') + + save : -> + actions = @props.flux.getProjectActions(@props.project.get('project_id')) + actions.set_public_path('', @refs.share_project.getValue()) + @setState(state : 'view') + + render_share_cancel_buttons : -> + + + + + + render_update_desc_button: -> + + + + + render_share : (shared) -> + if @state.state == 'edit' or shared +
e.preventDefault(); @save()}> + @setState(desc : @refs.share_project.getValue())} + placeholder = 'Give a description...' /> + {@render_share_cancel_buttons() if @state.state == 'edit'} + {@render_update_desc_button() if shared} +
+ + toggle_share : (shared) -> + actions = @props.flux.getProjectActions(@props.project.get('project_id')) + if shared + actions.disable_public_path('') + else + @setState(state : 'edit') + + render_share_unshare_button : (shared) -> + + render : -> + if not @props.public_paths? + return project_id = @props.project.get('project_id') - shared = @props.flux.getStore('projects').get_public_paths(project_id) - - + project_store = @props.flux.getProjectStore(project_id) + id = project_store.get_public_path_id('') + shared = @props.public_paths.get(id)? and not @props.public_paths.get(id).get('disabled') + if shared + share_message = "This project is publicly shared, so anyone can see it." + else + share_message = "Share this project publicly. You can also share individual files or folders from the file listing." + - Share this project publicly. You can also share individual files or folders from the file listing. + {share_message} - - {@render_share()} + {@render_share_unshare_button(shared) if @state.state == 'view'} -
- - Copy this entire project to a different project. - - - + + {@render_share(shared)}
@@ -846,14 +897,16 @@ ProjectSettings = rclass displayName : 'ProjectSettings-ProjectSettings' propTypes : - project : rtypes.object.isRequired - user_map : rtypes.object.isRequired - flux : rtypes.object.isRequired - - shouldComponentUpdate : (nextProps) -> - return @props.project != nextProps.project or @props.user_map != nextProps.user_map + project : rtypes.object.isRequired + user_map : rtypes.object.isRequired + flux : rtypes.object.isRequired + public_paths : rtypes.object.isRequired render : -> + # get the description of the share, in case the project is being shared + store = @props.flux.getProjectStore(@props.project.get('project_id')) + share_desc = @props.public_paths.get(store.get_public_path_id('')).get('description') ? '' +
{if @props.project.get('deleted') then }

Settings and configuration

@@ -866,6 +919,8 @@ ProjectSettings = rclass + @@ -875,10 +930,11 @@ ProjectController = rclass displayName : 'ProjectSettings-ProjectController' propTypes : - project_map : rtypes.object - user_map : rtypes.object - project_id : rtypes.string.isRequired - flux : rtypes.object + project_map : rtypes.object + user_map : rtypes.object + project_id : rtypes.string.isRequired + public_paths : rtypes.object + flux : rtypes.object getInitialState : -> admin_project : undefined # used in case visitor to project is admin @@ -908,7 +964,7 @@ ProjectController = rclass render: -> - if not @props.flux? or not @props.project_map? or not @props.user_map? + if not @props.flux? or not @props.project_map? or not @props.user_map? or not @props.public_paths? return user_map = @props.user_map project = @props.project_map?.get(@props.project_id) ? @state.admin_project @@ -924,14 +980,16 @@ ProjectController = rclass else
{@render_admin_message() if @state.admin_project?} - +
render = (project_id) -> + project_store = flux.getProjectStore(project_id) connect_to = project_map : 'projects' user_map : 'users' stripe_customer : 'account' # the QuotaConsole component depends on this in that it calls something in the account store! + public_paths : project_store.name diff --git a/salvus/page/project_store.coffee b/salvus/page/project_store.coffee index 6f1a69a124..8e931105b9 100644 --- a/salvus/page/project_store.coffee +++ b/salvus/page/project_store.coffee @@ -788,7 +788,8 @@ class ProjectActions extends Actions @process_results(err, output, max_results, max_output, cmd) class ProjectStore extends Store - _init : => + _init : (project_id) => + @project_id = project_id ActionIds = @flux.getActionIds(@name) @register(ActionIds.setTo, @setTo) @_account_store = @flux.getStore('account') @@ -919,6 +920,11 @@ class ProjectStore extends Store if @state.public_paths? return @_public_paths_cache ?= immutable.fromJS((misc.copy_without(x,['id','project_id']) for _,x of @state.public_paths.toJS())) + get_public_path_id: (path) => + # (this exists because rethinkdb doesn't have compound primary keys) + {SCHEMA, client_db} = require('schema') + return SCHEMA.public_paths.user_query.set.fields.id({project_id:@project_id, path:path}, client_db) + _compute_public_files: (x) => listing = x.listing pub = x.public @@ -949,7 +955,7 @@ exports.getStore = getStore = (project_id, flux) -> actions = flux.createActions(name, ProjectActions) actions._init(project_id) store = flux.createStore(name, ProjectStore) - store._init() + store._init(project_id) queries = misc.deep_copy(QUERIES)