diff --git a/core/src/plugins/action.share/Gruntfile.js b/core/src/plugins/action.share/Gruntfile.js new file mode 100644 index 0000000000..4210b70d69 --- /dev/null +++ b/core/src/plugins/action.share/Gruntfile.js @@ -0,0 +1,34 @@ +module.exports = function(grunt) { + grunt.initConfig({ + babel: { + options: {}, + + dist: { + files: [ + { + expand: true, + cwd: 'res/react/', + src: ['**/*.js'], + dest: 'res/build/', + ext: '.js' + } + ] + } + }, + watch: { + js: { + files: [ + "res/react/**/*" + ], + tasks: ['babel'], + options: { + spawn: false + } + } + } + }); + grunt.loadNpmTasks('grunt-babel'); + grunt.loadNpmTasks('grunt-contrib-watch'); + grunt.registerTask('default', ['babel']); + +}; \ No newline at end of file diff --git a/core/src/plugins/action.share/manifest.xml b/core/src/plugins/action.share/manifest.xml index eca9ac0a51..4b89b79294 100644 --- a/core/src/plugins/action.share/manifest.xml +++ b/core/src/plugins/action.share/manifest.xml @@ -31,12 +31,35 @@ + + + + + + + + + + + + + ]]> + + diff --git a/core/src/plugins/action.share/package.json b/core/src/plugins/action.share/package.json new file mode 100644 index 0000000000..605423d741 --- /dev/null +++ b/core/src/plugins/action.share/package.json @@ -0,0 +1,17 @@ +{ + "name": "action.share", + "version": "6.2.3", + "description": "", + "source_path":"react", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Abstrium SAS", + "license": "AGPL", + "devDependencies": { + "grunt": "~0.4.5", + "grunt-babel": "~5.0.3", + "grunt-contrib-watch": "~0.6.1" + } +} diff --git a/core/src/plugins/action.share/res/react-share-form.css b/core/src/plugins/action.share/res/react-share-form.css new file mode 100644 index 0000000000..29739a7f0c --- /dev/null +++ b/core/src/plugins/action.share/res/react-share-form.css @@ -0,0 +1,239 @@ +div.form-react_share_form div.dialogTitle { + display: none; +} +div#react_share_form { + font-size: 13px; +} +div#react_share_form * { + font-family: Roboto; +} +div#react_share_form [class^="icon-"], +div#react_share_form [class*="icon-"] { + font-family: FontAwesome; +} +div#react_share_form div.headerPanel { + background-color: #4aceb0 !important; +} +div#react_share_form .mui-tabs-container .mui-tab-item-container { + background-color: #4aceb0 !important; +} +div#react_share_form .mui-tabs-container .mui-tab-template { + min-height: 300px; +} +div#react_share_form .shared-users-rights-header { + color: #ADADAD; + padding-right: 50px; + text-align: right; +} +div#react_share_form .shared-users-rights-header span { + display: inline-block; + font-size: 10px; + margin: 0 6px; + text-transform: uppercase; +} +div#react_share_form .suggest-search.icon-search { + color: #C1C1C1; + font-size: 18px; + position: absolute; + right: 15px; + top: 2px; +} +div#react_share_form .save-as-team-container { + text-align: right; + margin-top: 6px; + padding-right: 15px; +} +div#react_share_form .save-as-team-container a { + color: #c1c1c1; + text-decoration: underline; + font-size: 14px; + cursor: pointer; +} +div#react_share_form div.mui-drop-down-menu.full-width { + width: 400px; + margin-left: -10px; +} +div#react_share_form div.mui-drop-down-menu.full-width .mui-menu-control .mui-menu-label { + white-space: nowrap; + width: 365px; + overflow: hidden; + text-overflow: ellipsis; +} +div#react_share_form .public-link-container { + padding: 3px 6px 15px; + background-color: #F1F1F1; + border-radius: 8px; + margin: 16px 0 6px; +} +div#react_share_form .public-link-container .public-link { + width: 350px; + font-size: 20px; +} +div#react_share_form .public-link-container .public-link input { + text-align: center; + color: #43987c; +} +div#react_share_form .public-link-container.edit-link > span { + font-size: 20px; + text-align: right; + display: inline-block; + width: 160px; + color: #43987c; +} +div#react_share_form .public-link-container.edit-link .mui-raised-button { + margin-left: 10px; +} +div#react_share_form .public-link-container.edit-link .mui-text-field { + font-size: 20px; + width: 100px; +} +div#react_share_form .custom-link-button.icon-edit-sign { + color: #ddd; + font-size: 20px; + cursor: pointer; + display: inline-block; + padding-left: 5px; +} +div#react_share_form .custom-link-button.icon-edit-sign:hover { + color: #47b092; +} +div#react_share_form .password-container, +div#react_share_form .expires { + margin-top: -10px; +} +div#react_share_form .password-container .mui-text-field, +div#react_share_form .expires .mui-text-field { + width: 96%; +} +div#react_share_form .label-desc-edit .mui-text-field { + width: 100%; + margin-top: -10px; +} +div#react_share_form h3 { + font-size: 22px; +} +div#react_share_form h4 { + padding-top: 10px; + font-weight: normal; + font-size: 17px; +} +div#react_share_form .ownership-form .mui-text-field { + margin-top: -20px; + width: 230px; + margin-right: 10px; +} +div#react_share_form div.user-badge { + border-bottom: 1px solid #e2e2e2; + clear: both; + font-size: 16px; + margin-left: 50px; + margin-right: 11px; + padding-top: 1px; +} +div#react_share_form div.user-badge:last-of-type { + border-bottom: 0; +} +div#react_share_form div.user-badge span.icon-ellipsis-vertical.mui-font-icon { + color: #6F6F6F; + font-size: 18px; +} +div#react_share_form div.user-badge span.avatar { + background-color: #4aceb0; + border-radius: 30px; + color: white; + display: inline-block; + font-size: 17px; + height: 32px; + margin: 5px 14px 7px -44px; + padding: 6px; + text-align: center; + width: 32px; +} +div#react_share_form div.user-badge.user-type-group span.avatar { + background-color: #47b092; +} +div#react_share_form div.user-badge.user-type-tmp_user span.avatar { + background-color: #438db3; +} +div#react_share_form div.user-badge img { + background-color: #4aceb0; + border-radius: 30px; + color: white; + display: inline-block; + font-size: 17px; + height: 32px; + margin: 5px 14px 7px -44px; + padding: 6px; + text-align: center; + width: 32px; +} +div#react_share_form div.user-badge div.user-badge-menu-box { + float: right; + font-size: 13px; + position: relative; +} +div#react_share_form div.user-badge div.user-badge-menu-box div.mui-menu.mui-visible { + box-shadow: 0 0 5px rgba(0, 0, 0, 0.43); + position: absolute; + right: 0; + top: 0; + width: 200px; + z-index: 120; +} +div#react_share_form div.user-badge div.user-badge-menu-box div.mui-menu span.icon-check { + float: right; + font-size: 16px; + margin-top: 15px; +} +div#react_share_form div.user-badge span.user-badge-rights-container { + float: right; + padding: 11px; +} +div#react_share_form div.user-badge span.user-badge-rights-container input[name="write"] { + margin-left: 28px; +} +div.react-autosuggest { + padding-left: 4px; +} +div.react-autosuggest .react-autosuggest__suggestion--focused { + background-color: aliceblue; +} +div.react-autosuggest input.react-autosuggest__input { + width: 370px; +} +div.react-autosuggest .react-autosuggest__suggestions { + background-color: white; + box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.63); + display: block; + margin-top: 1px; + max-height: 300px; + overflow-y: auto; + position: absolute; + width: 370px; + z-index: 20; +} +div.react-autosuggest input#users-autosuggest { + font-size: 18px; + padding-bottom: 9px !important; + padding-left: 4px !important; +} +.dialogContent div.reset-pydio-forms input { + border: 0; + margin: 0; + padding: 0; + border-radius: 0; + height: inherit; + font-size: inherit; + background-color: transparent; +} +.dialogContent div.reset-pydio-forms input:disabled { + background-color: transparent !important; +} +.dialogContent div.reset-pydio-forms .mui-text-field.mui-has-floating-labels .mui-text-field-input { + padding-top: 24px !important; +} +.dialogContent div.reset-pydio-forms input[type="checkbox"], +.dialogContent div.reset-pydio-forms .dialogContent input[type="radio"] { + height: 100%; + width: 100%; +} diff --git a/core/src/plugins/action.share/res/react-share-form.less b/core/src/plugins/action.share/res/react-share-form.less new file mode 100644 index 0000000000..832a03d170 --- /dev/null +++ b/core/src/plugins/action.share/res/react-share-form.less @@ -0,0 +1,272 @@ +// Color variables (appears count calculates by raw css) +@color0: #4aceb0; +@color1: #47b092; +@color2: #43987c; +@color3: rgb(67, 141, 179); + +// Width variables (appears count calculates by raw css) +@width0: 370px; // Appears 2 times +@width2: 32px; // Appears 2 times + +// Height variables (appears count calculates by raw css) +@height1: 32px; // Appears 2 times + +div.form-react_share_form { + div.dialogTitle { + display: none; + } +} + +div#react_share_form { + * { + font-family: Roboto; + } + [class^="icon-"],[class*="icon-"]{ + font-family: FontAwesome; + } + font-size:13px; + div.headerPanel { + background-color: @color0 !important; + } + .mui-tabs-container { + .mui-tab-item-container { + background-color: @color0 !important; + } + .mui-tab-template { + min-height: 300px; + } + } + .shared-users-rights-header { + color: #ADADAD; + padding-right: 50px; + text-align: right; + span { + display: inline-block; + font-size: 10px; + margin: 0 6px; + text-transform: uppercase; + } + } + .suggest-search.icon-search { + color: #C1C1C1; + font-size: 18px; + position: absolute; + right: 15px; + top: 2px; + } + .save-as-team-container{ + text-align: right; + margin-top: 6px; + padding-right: 15px; + a{ + color:#c1c1c1; + text-decoration: underline; + font-size: 14px; + cursor: pointer; + } + } + div.mui-drop-down-menu.full-width{ + width: 400px; + margin-left: -10px; + .mui-menu-control .mui-menu-label{ + white-space: nowrap; + width: 365px; + overflow: hidden; + text-overflow: ellipsis; + } + } + .public-link-container{ + padding: 3px 6px 15px; + background-color: #F1F1F1; + border-radius: 8px; + margin: 16px 0 6px; + .public-link{ + width: 350px; + font-size: 20px; + input{ + text-align: center; + color: @color2; + } + } + &.edit-link{ + > span{ + font-size: 20px; + text-align: right; + display: inline-block; + width: 160px; + color: @color2; + } + .mui-raised-button{ + margin-left: 10px; + } + .mui-text-field{ + font-size: 20px; + width: 100px; + } + } + } + .custom-link-button.icon-edit-sign{ + color: #ddd; + font-size: 20px; + cursor: pointer; + display: inline-block; + padding-left: 5px; + } + .custom-link-button.icon-edit-sign:hover{ + color: @color1; + } + .password-container, + .expires + { + margin-top: -10px; + .mui-text-field{ + width: 96%; + } + } + .label-desc-edit{ + .mui-text-field{ + width: 100%; + margin-top: -10px; + } + } + .section-legend{ + + } + h3{ + font-size: 22px; + } + h4{ + padding-top: 10px; + font-weight: normal; + font-size: 17px; + } + .ownership-form{ + .mui-text-field{ + margin-top: -20px; + width: 230px; + margin-right: 10px; + } + } + div.user-badge { + border-bottom: 1px solid #e2e2e2; + clear: both; + font-size: 16px; + margin-left: 50px; + margin-right: 11px; + padding-top: 1px; + &:last-of-type { + border-bottom: 0; + } + span.icon-ellipsis-vertical.mui-font-icon { + color: #6F6F6F; + font-size: 18px; + } + span.avatar { + background-color: @color0; + border-radius: 30px; + color: white; + display: inline-block; + font-size: 17px; + height: @height1; + margin: 5px 14px 7px -44px; + padding: 6px; + text-align: center; + width: @width2; + } + &.user-type-group{ + span.avatar{ + background-color: @color1; + } + } + &.user-type-tmp_user{ + span.avatar{ + background-color: @color3; + } + } + img { + background-color: @color0; + border-radius: 30px; + color: white; + display: inline-block; + font-size: 17px; + height: @height1; + margin: 5px 14px 7px -44px; + padding: 6px; + text-align: center; + width: @width2; + } + div.user-badge-menu-box { + float: right; + font-size: 13px; + position: relative; + div.mui-menu.mui-visible { + box-shadow: 0 0 5px rgba(0,0,0,0.43); + position: absolute; + right: 0; + top:0; + width: 200px; + z-index: 120; + } + div.mui-menu { + span.icon-check { + float: right; + font-size: 16px; + margin-top: 15px; + } + } + } + span.user-badge-rights-container { + float: right; + padding: 11px; + input[name="write"] { + margin-left: 28px; + } + } + } +} +div.react-autosuggest { + padding-left: 4px; + .react-autosuggest__suggestion--focused { + background-color: aliceblue; + } + input.react-autosuggest__input { + width: @width0; + } + .react-autosuggest__suggestions { + background-color: white; + box-shadow: 1px 1px 5px rgba(0,0,0,0.63); + display: block; + margin-top: 1px; + max-height: 300px; + overflow-y: auto; + position: absolute; + width: @width0; + z-index: 20; + } + input#users-autosuggest { + font-size: 18px; + padding-bottom: 9px !important; + padding-left: 4px !important; + } +} +.dialogContent div.reset-pydio-forms{ + input{ + border:0; + margin: 0; + padding: 0; + border-radius: 0; + height: inherit; + font-size: inherit; + background-color: transparent; + &:disabled{ + background-color: transparent !important; + } + } + .mui-text-field.mui-has-floating-labels .mui-text-field-input{ + padding-top: 24px !important; + } + input[type="checkbox"], .dialogContent input[type="radio"]{ + height: 100%; + width: 100%; + } +} \ No newline at end of file diff --git a/core/src/plugins/action.share/res/react/ShareDialog.js b/core/src/plugins/action.share/res/react/ShareDialog.js new file mode 100644 index 0000000000..ab4bdb80db --- /dev/null +++ b/core/src/plugins/action.share/res/react/ShareDialog.js @@ -0,0 +1,971 @@ +/* + * Copyright 2007-2013 Charles du Jeu - Abstrium SAS + * This file is part of Pydio. + * + * Pydio is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Pydio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Pydio. If not, see . + * + * The latest code can be found at . + */ +(function(global) { + + var UserBadge; + var MainPanel = React.createClass({ + + propTypes: { + closeAjxpDialog: React.PropTypes.func.isRequired, + pydio:React.PropTypes.instanceOf(Pydio).isRequired, + selection:React.PropTypes.instanceOf(PydioDataModel).isRequired + }, + + refreshDialogPosition:function(){ + global.pydio.UI.modal.refreshDialogPosition(); + }, + + modelUpdated: function(eventData){ + if(this.isMounted()){ + this.setState({ + status: eventData.status, + model:eventData.model + }, function(){ + this.refreshDialogPosition(); + }.bind(this)); + if(eventData.status == "saved"){ + this.props.pydio.fireNodeRefresh(this.props.selection.getUniqueNode()); + } + } + }, + + getInitialState: function(){ + return { + status: 'idle', + model: new ReactModel.Share(this.props.pydio, this.props.selection) + }; + }, + + componentDidMount: function(){ + this.state.model.observe("status_changed", this.modelUpdated); + }, + + clicked: function(){ + this.props.closeAjxpDialog(); + }, + + render: function(){ + var model = this.state.model; + var panels = []; + var auth = ReactModel.Share.getAuthorizations(this.props.pydio); + if((model.getNode().isLeaf() && auth.file_public_link) || (!model.getNode().isLeaf() && auth.folder_public_link)){ + panels.push( + + + + ); + } + if( (model.getNode().isLeaf() && auth.file_workspaces) || (!model.getNode().isLeaf() && auth.folder_workspaces)){ + var users = model.getSharedUsers(); + panels.push( + + + + ); + } + if(panels.length > 0){ + panels.push( + + + + ); + } + + return( +
+ + {panels} + +
+ ); + } + + }); + + var HeaderPanel = React.createClass({ + render: function(){ + return ( +
+
Share {PathUtils.getBasename(this.props.shareModel.getNode().getPath())}
+
+ ); + } + }); + + var ButtonsPanel = React.createClass({ + propTypes: { + onClick: React.PropTypes.func.isRequired + }, + triggerModelSave: function(){ + this.props.shareModel.save(); + }, + render: function(){ + if(this.props.shareModel.getStatus() == 'modified'){ + return ( +
+ + +
+ ); + }else{ + return ( +
+ +
+ ); + } + } + }); + + /**************************/ + /* USERS PANEL + /**************************/ + var UsersPanel = React.createClass({ + propTypes:{ + shareModel:React.PropTypes.instanceOf(ReactModel.Share) + }, + onUsersUpdate: function(operation, userId, userData){ + this.props.shareModel.updateSharedUser(operation, userId, userData); + }, + onSaveSelection:function(){ + var label = window.prompt(global.pydio.MessageHash[510]); + if(!label) return; + this.props.shareModel.saveSelectionAsTeam(label); + }, + valueSelected: function(id, label, type){ + var newEntry = { + ID: id, + RIGHT:'r', + LABEL: label, + TYPE:type + }; + this.props.shareModel.updateSharedUser('add', newEntry.ID, newEntry); + }, + render: function(){ + var currentUsers = this.props.shareModel.getSharedUsers(); + const excludes = currentUsers.map(function(u){return u.ID}); + return ( +
+ + +
+ ); + } + }); + + UserBadge = React.createClass({ + propTypes: { + label: React.PropTypes.string, + avatar: React.PropTypes.string, + type:React.PropTypes.string, + menus: React.PropTypes.object + }, + getInitialState(){ + return {showMenu:false}; + }, + showMenu: function () { + this.setState({showMenu: true}); + }, + /****************************/ + /* WARNING: PROTOTYPE CODE + */ + hideMenu: function(event){ + if(event && event.target.up('.mui-icon-button')){ + return; + } + this.setState({showMenu: false}); + }, + componentDidMount: function(){ + this._observer = this.hideMenu.bind(this); + document.observe('click', this._observer); + }, + componentWillUnmount: function(){ + document.stopObserving('click', this._observer); + }, + /* + /* END PROTOTYPE CODE + /***************************/ + + menuClicked:function(event, index, menuItem){ + if(menuItem.payload){ + menuItem.payload(); + } + this.hideMenu(); + }, + renderMenu: function(){ + if (!this.props.menus) { + return null; + } + var menuAnchor = ; + if(this.state.showMenu) { + const menuItems = this.props.menus.map(function(m){ + var text = m.text; + if(m.checked){ + text = {m.text}; + } + return {text:text, payload:m.callback}; + }); + var menuBox = ; + } + return ( +
+ {menuAnchor} + {menuBox} +
+ ); + }, + + render: function () { + var avatar; + /* + if (this.props.avatar) { + avatar = ( + + + + ); + }else{ + avatar = ; + }*/ + if(this.props.type == 'group') { + avatar = ; + }else if(this.props.type == 'temporary'){ + avatar = ; + }else{ + avatar = ; + } + var menu = this.renderMenu(); + return ( +
+ {menu} + {avatar} + {this.props.label} + {this.props.children} +
+ ); + } + }); + + var SharedUsersBox = React.createClass({ + propTypes: { + users:React.PropTypes.array.isRequired, + onUsersUpdate:React.PropTypes.func.isRequired, + saveSelectionAsTeam:React.PropTypes.func + }, + render: function(){ + // sort by group/user then by ID; + const userEntries = this.props.users.sort(function(a,b) { + return (b.TYPE == "group") ? 1 : ((a.TYPE == "group") ? -1 : (a.ID > b.ID) ? 1 : ((b.ID > a.ID) ? -1 : 0)); + } ).map(function(u){ + return + }.bind(this)); + if(this.props.saveSelectionAsTeam && this.props.users.length > 1){ + var saveSelection = ( + + ); + } + var rwHeader; + if(this.props.users.length){ + rwHeader = ( +
+
+ Read + Modify +
+
+ ); + }else{ + rwHeader = ( +
Use the field above to pick a user from the internal directory or from your personal address book. If you want to create a new user, just type in a new identifier and hit Enter.
+ ); + } + return ( +
+ {rwHeader} +
{userEntries}
+ {saveSelection} +
+ ); + } + }); + + var SharedUserEntry = React.createClass({ + propTypes: { + userEntry:React.PropTypes.object.isRequired, + onUserUpdate:React.PropTypes.func.isRequired + }, + onRemove:function(){ + this.props.onUserUpdate('remove', this.props.userEntry.ID, this.props.userEntry); + }, + onToggleWatch:function(){ + this.props.onUserUpdate('update_right', this.props.userEntry.ID, {right:'watch', add:!this.props.userEntry['WATCH']}); + }, + onInvite:function(){ + + }, + onUpdateRight:function(event){ + var target = event.target; + this.props.onUserUpdate('update_right', this.props.userEntry.ID, {right:target.name, add:target.checked}); + }, + render: function(){ + var menuItems = []; + if(this.props.userEntry.TYPE != 'group'){ + menuItems.push({text:'Notify on content changes', callback:this.onToggleWatch, checked:this.props.userEntry.WATCH}); + menuItems.push({text:'Send invitation', callback:this.onInvite}); + } + menuItems.push({text:'Remove', callback:this.onRemove}); + return ( + + + + + + + ); + } + }); + + var UsersLoader = React.createClass({ + + propTypes:{ + onValueSelected:React.PropTypes.func.isRequired, + excludeValues:React.PropTypes.array.isRequired + }, + + getInitialState:function(){ + return {createUser: null}; + }, + + getSuggestions(input, callback){ + + var excludes = this.props.excludes; + PydioApi.getClient().request({get_action:'user_list_authorized_users', value:input, format:'xml'}, function(transport){ + const lis = XMLUtils.XPathSelectNodes(transport.responseXML, '//li'); + var suggestions = []; + lis.map(function(li){ + var id = li.getAttribute('data-entry_id'); + if(id && excludes.indexOf(id) !== -1){ + return; + } + var spanLabel = XMLUtils.XPathGetSingleNodeText(li, 'span[@class="user_entry_label"]'); + suggestions.push({ + label:li.getAttribute('data-label'), + spanLabel:spanLabel, + id:li.getAttribute('data-entry_id'), + type:li.getAttribute('class'), + group:li.getAttribute('data-group'), + avatar:li.getAttribute('data-avatar'), + temporary:li.getAttribute('data-temporary')?true:false, + external:li.getAttribute('data-external') == 'true' + }); + }); + callback(null, suggestions); + }); + + }, + + renderSuggestion: function(suggestion, input){ + return ( + + ); + }, + + suggestionValue: function(suggestion){ + return '';//suggestion.id || suggestion.label; + }, + + onSuggestionSelected: function(suggestion, event){ + if(!suggestion) return; + var blur = true; + if(suggestion.group){ + this.props.onValueSelected(suggestion.group, suggestion.label, 'group'); + }else if(suggestion.id) { + this.props.onValueSelected(suggestion.id, suggestion.label, suggestion.external?'tmp_user':'user'); + }else if(suggestion.temporary){ + this.setState({createUser:suggestion.label}); + blur = false; + } + if(blur){ + this.refs.autosuggest.refs.input.getDOMNode().blur(); + global.setTimeout(function(){ + this.refs.autosuggest.refs.input.getDOMNode().blur(); + }.bind(this), 50); + } + }, + + submitCreationForm: function(){ + + var values = this.refs['creationForm'].getValuesForPost(); + values['get_action'] = 'user_create_user'; + PydioApi.getClient().request(values, function(transport){ + console.log(transport.responseText); + var display = values.NEW_USER_DISPLAY_NAME || values.NEW_new_user_id; + this.props.onValueSelected(values.NEW_new_user_id, display, 'user'); + this.setState({createUser:null}); + }.bind(this)); + + }, + + cancelCreationForm:function(){ + this.setState({createUser:null}); + }, + + render: function(){ + + if(this.state.createUser){ + + return ( +
+ +
+ +
+ + +
+
+ +
+ ); + + }else{ + const inputAttributes = { + id: 'users-autosuggest', + name: 'users-autosuggest', + className: 'react-autosuggest__input', + placeholder: 'Filter users or create one...', + value: '' // Initial value + }; + return ( +
+ + true } + inputAttributes={inputAttributes} + suggestions={this.getSuggestions} + suggestionRenderer={this.renderSuggestion} + suggestionValue={this.suggestionValue} + onSuggestionSelected={this.onSuggestionSelected} + /> +
+ ); + } + } + + }); + + var UserCreationForm = React.createClass({ + + propTypes:{ + newUserName:React.PropTypes.string.isRequired + }, + + getParameters: function(){ + + if(this._parsedParameters){ + return this._parsedParameters; + } + + var basicParameters = []; + basicParameters.push({ + description: MessageHash['533'], + editable: false, + expose: "true", + label: MessageHash['522'], + name: "new_user_id", + scope: "user", + type: "string", + mandatory: "true" + },{ + description: MessageHash['534'], + editable: "true", + expose: "true", + label: MessageHash['523'], + name: "new_password", + scope: "user", + type: "password", + mandatory: "true" + },{ + description: MessageHash['536'], + editable: "true", + expose: "true", + label: MessageHash['535'], + name: "send_email", + scope: "user", + type: "boolean", + mandatory: true + }); + + var params = global.pydio.getPluginConfigs('conf').get('NEWUSERS_EDIT_PARAMETERS').split(','); + for(var i=0;i + } + }); + + /**************************/ + /* PUBLIC LINK PANEL + /**************************/ + var PublicLinkPanel = React.createClass({ + + propTypes: { + pydio:React.PropTypes.instanceOf(Pydio), + shareModel: React.PropTypes.instanceOf(ReactModel.Share), + authorizations: React.PropTypes.object + }, + + toggleLink: function(event){ + this.props.shareModel.togglePublicLink(); + }, + + render: function(){ + + + if(this.props.shareModel.hasPublicLink()){ + var publicLinkPanes = [ + , + + ]; + /* + var layoutData = ReactModel.Share.compileLayoutData(this.props.pydio, this.props.shareModel.getNode()); + if(!this.props.shareModel.getNode().isLeaf() && layoutData.length > 1){ + publicLinkPanes.push(); + } + */ + } + return ( +
+ + + {publicLinkPanes} +
+ ); + } + }); + + var PublicLinkField = React.createClass({ + propTypes: { + shareModel: React.PropTypes.instanceOf(ReactModel.Share), + editAllowed: React.PropTypes.bool, + onChange: React.PropTypes.func + }, + getInitialState: function(){ + return {editLink: false} + }, + toggleEditMode: function(){ + if(this.state.editLink && this.state.customLink){ + this.props.shareModel.updateCustomLink(this.state.customLink); + } + this.setState({editLink: !this.state.editLink}); + }, + changeLink:function(event){ + this.setState({customLink: event.target.value}); + }, + + render: function(){ + var publicLink = this.props.shareModel.getPublicLink(); + var editAllowed = this.props.editAllowed && !this.props.shareModel.publicLinkIsShorten(); + if(this.state.editLink && editAllowed){ + return ( +
+ {publicLink.split('://')[0]}://[..]/{PathUtils.getBasename(PathUtils.getDirname(publicLink)) + '/'} + + +
You can customize the last part of the link.
+
+ ); + }else{ + if(editAllowed && publicLink){ + var editButton = ; + } + var copyMessage; + if( global.navigator.platform.indexOf("Mac") === 0 ){ + copyMessage = global.pydio.MessageHash['share_center.144']; + }else{ + copyMessage = global.pydio.MessageHash['share_center.143']; + } + var setHtml = function(){ + return {__html:copyMessage}; + }; + if(publicLink){ + var focus = function(e){ + e.target.select(); + }; + return ( +
+ {editButton} +
+
+ ); + }else{ + return ( +
This file is not currently publicly accessible. Enabling a public link will create a unique access that you can send to anyone. If you want to share with existing Pydio users, use the "Users" tab.
+ ); + } + } + } + }); + + var PublicLinkPermissions = React.createClass({ + + changePermission: function(event){ + var name = event.target.name; + var checked = event.target.checked; + this.props.shareModel.setPublicLinkPermission(name, checked); + }, + + render: function(){ + var perms = [], previewWarning; + perms.push({NAME:'read',LABEL:'Preview'}); + perms.push({NAME:'download', LABEL:'Download'}); + if(!this.props.shareModel.getNode().isLeaf()){ + perms.push({NAME:'write', LABEL:'Upload'}); + } + if(this.props.shareModel.isPublicLinkPreviewDisabled() && this.props.shareModel.getPublicLinkPermission('read')){ + previewWarning =
Warning, there is no embedded viewer for this file, except opening in a new tab of your browser: this may trigger a download automatically when user opens the link.
; + } + return ( +
+

Permissions

+
How users are allowed to preview/modify content.
+
+ {perms.map(function(p){ + return ( +
+ +
+ ); + }.bind(this))} + {previewWarning} +
+
+ ); + } + }); + + var PublicLinkSecureOptions = React.createClass({ + + updateDLExpirationField: function(event){ + var newValue = event.currentTarget.getValue(); + this.props.shareModel.setExpirationFor("downloads", newValue); + }, + + updateDaysExpirationField: function(event){ + var newValue = event.currentTarget.getValue(); + this.props.shareModel.setExpirationFor("days", newValue); + }, + + resetPassword: function(){ + this.props.shareModel.resetPassword(); + }, + + updatePassword: function(event){ + var newValue = event.currentTarget.getValue(); + this.props.shareModel.updatePassword(newValue); + }, + + render: function(){ + var passPlaceHolder, resetPassword; + if(this.props.shareModel.hasHiddenPassword()){ + passPlaceHolder = '********'; + resetPassword = + } + return ( +
+

Secure Access

+
Protect the link with a password, or make it expire automatically.
+
+
+ +
+
+ {resetPassword} +
+
+
+
+ +
+
+ +
+
+
+ ); + } + }); + + var PublicLinkTemplate = React.createClass({ + + onDropDownChange: function(event, index, item){ + this.props.shareModel.setTemplate(item.payload); + }, + + render: function(){ + var index = 0, crtIndex = 0; + var selected = this.props.shareModel.getTemplate(); + var menuItems=this.props.layoutData.map(function(l){ + if(selected && l.LAYOUT_ELEMENT == selected) { + crtIndex = index; + } + index ++; + return {payload:l.LAYOUT_ELEMENT, text:l.LAYOUT_LABEL}; + }); + return ( +
+

Link Layout

+
You can select the appearance of the link as it will appear in the browser.
+ +
+ ); + } + }); + + /**************************/ + /* ADVANCED PANEL + /**************************/ + var AdvancedPanel = React.createClass({ + propTypes:{ + pydio:React.PropTypes.instanceOf(Pydio), + shareModel:React.PropTypes.instanceOf(ReactModel.Share) + }, + render: function(){ + + var layoutData = ReactModel.Share.compileLayoutData(this.props.pydio, this.props.shareModel.getNode()); + if(!this.props.shareModel.getNode().isLeaf() && layoutData.length > 1){ + var layoutPane = ; + } + + return ( +
+ + + {layoutPane} + +
+ ); + } + }); + + var LabelDescriptionPanel = React.createClass({ + + updateLabel: function(event){ + this.props.shareModel.setGlobal("label", event.currentTarget.value); + }, + + updateDescription: function(event){ + this.props.shareModel.setGlobal("description", event.currentTarget.value); + }, + + render: function(){ + return ( +
+

Share Label

+
These are displayed to the user accessing this share.
+
+ + +
+
+ ); + } + }); + + var NotificationPanel = React.createClass({ + + dropDownChange:function(event, index, item){ + this.props.shareModel.setGlobal('watch', (index!=0)); + }, + + render: function(){ + var menuItems = [ + {payload:'no_watch', text:'Do not notify me'}, + {payload:'watch_read', text:'Notify me when share is accessed'}, + {payload:'watch_write', text:'Notify me when share is modified'} + ]; + var selectedIndex = this.props.shareModel.getGlobal('watch') ? 1 : 0; + return ( +
+

Notification

+
Be alerted whenever a user accesses a file.
+ +
+ ); + } + }); + + var VisibilityPanel = React.createClass({ + toggleVisibility: function(){ + this.props.shareModel.toggleVisibility(); + }, + transferOwnership: function(){ + this.props.shareModel.setNewShareOwner(this.refs['newOwner'].getValue()); + }, + render: function(){ + var currentIsOwner = global.pydio.user.id == this.props.shareModel.getShareOwner(); + + var legend; + if(currentIsOwner){ + legend = "Other users who access to the current workspace can update the links parameters, but they cannot delete it. Only you can stop this share or toggle its visibility"; + }else{ + legend = "Other users who access to the current workspace can update the links parameters. You are not the owner of the share so you cannot delete it or toggle its visibility"; + } + var showToggle = ( +
+ +
{legend}
+
+ ); + if(this.props.shareModel.isPublic() && currentIsOwner){ + var showTransfer = ( +
+

Transfer Ownership

+
If the share is publicly visible and you want another user to manage this share, you can transfer its ownership.
+
+ + +
+
+ ); + } + return ( +
+

Share Visibility

+ {showToggle} + {showTransfer} +
+ ); + } + }); + + var DialogNamespace = global.ShareDialog || {}; + DialogNamespace.MainPanel = MainPanel; + global.ShareDialog = DialogNamespace; + +})(window); \ No newline at end of file diff --git a/core/src/plugins/action.share/res/react/model/ShareModel.js b/core/src/plugins/action.share/res/react/model/ShareModel.js new file mode 100644 index 0000000000..5e2c4dfa9f --- /dev/null +++ b/core/src/plugins/action.share/res/react/model/ShareModel.js @@ -0,0 +1,598 @@ +(function(global) { + + class ShareModel extends Observable { + + + constructor(pydio, userSelection){ + super(); + this._userSelection = userSelection; + this._node = userSelection.getUniqueNode(); + this._status = 'idle'; + this._edit = false; + this._data = {}; + this._pendingData = {}; + this._pydio = pydio; + if(this._node.getMetadata().get('ajxp_shared')){ + this.load(); + this._edit = true; + } + if(this._node.isLeaf()){ + this._previewEditors = pydio.Registry.findEditorsForMime(this._node.getAjxpMime()).filter(function(entry){ + return !(entry.editorClass == "OtherEditorChooser" || entry.editorClass == "BrowserOpener"); + }); + + } + } + + getNode(){ + return this._node; + } + + getSelectionLabel(){ + return this._node.getLabel(); + } + + getStatus(){ + return this._status; + } + + hasPublicLink(){ + return (this._data['minisite'] && this._data['minisite']['public_link']); + } + + getPublicLink(){ + if(this.hasPublicLink()){ + return this._data['minisite']['public_link']; + }else{ + return null; + } + } + + getPublicLinkHash(){ + if(this.hasPublicLink()){ + return this._data['minisite']['hash']; + }else{ + return null; + } + } + + publicLinkIsShorten(){ + if(this.hasPublicLink()){ + return this._data['minisite']['hash_is_shorten']; + }else{ + return false; + } + } + + togglePublicLink(){ + this._pendingData['enable_public_link'] = !this.hasPublicLink(); + this.save(); + } + + _initPendingData(){ + if(!this._pendingData['minisite']){ + this._pendingData['minisite'] = { + permissions:{}, + expiration:{} + }; + } + if(!this._pendingData['entries']){ + this._pendingData['entries'] = []; + if(this._data['entries']){ + // Deep duplicate + this._pendingData['entries'] = JSON.parse(JSON.stringify(this._data['entries'])); + } + } + } + + getSharedUsers(){ + var data = [], sharedData = []; + if(this._pendingData['entries']){ + data = this._pendingData['entries']; + }else if(this._data['entries']){ + data = this._data['entries']; + } + // Skip minisite temporary user + data.map(function(entry){ + if(!entry['HIDDEN']) sharedData.push(entry); + }); + return sharedData; + } + + updateSharedUser(operation, userId, userData){ + this._initPendingData(); + if(userData['ID']) { + userData['ID'] = userId; + } + var updatedData = []; + if(operation == 'add'){ + this._pendingData['entries'].push(userData); + }else if(operation == 'remove'){ + this._pendingData['entries'].map(function(entry){ + if(entry['ID'] != userId) updatedData.push(entry); + }); + this._pendingData['entries'] = updatedData; + }else if(operation == 'update') { + this._pendingData['entries'].map(function (entry) { + if (entry['ID'] != userId) updatedData.push(entry); + else updatedData.push(userData); + }); + this._pendingData['entries'] = updatedData; + }else if(operation == 'update_right'){ + // UserData is {right:'read'|'right', add:true|false} + this._pendingData['entries'].map(function (entry) { + if (entry['ID'] != userId) { + updatedData.push(entry); + } + else { + if(userData['right'] == 'watch'){ + entry.WATCH = userData['add']; + }else{ + var crtRead = (entry.RIGHT.indexOf('r') !== -1 || (userData['right'] == 'read' && userData['add'])) && !(userData['right'] == 'read' && !userData['add']); + var crtWrite = (entry.RIGHT.indexOf('w') !== -1 || (userData['right'] == 'write' && userData['add'])) && !(userData['right'] == 'write' && !userData['add']); + if(!crtRead && !crtWrite){ + crtRead = true; + } + entry.RIGHT = (crtRead ? 'r' : '') + (crtWrite ? 'w' : ''); + } + updatedData.push(entry); + } + }); + this._pendingData['entries'] = updatedData; + + }else{ + throw new Error('Unsupported operation, should be add, update, update_right or remove'); + } + this._setStatus('modified'); + } + + _sharedUsersToParameters(params){ + var entries = this.getSharedUsers(); + var index = 0; + entries.map(function(e){ + params['user_' + index] = e.ID; + params['right_read_' + index] = (e.RIGHT.indexOf('r') !== -1) ? 'true' : 'false'; + params['right_write_' + index] = (e.RIGHT.indexOf('w') !== -1) ? 'true' : 'false'; + if(e.WATCH){ + params['right_watch_' + index] = 'true'; + } + params['entry_type_' + index] = e.TYPE == 'group' ? 'group' : 'user'; + index ++; + }); + } + + saveSelectionSupported(pydio){ + return pydio.getController().actions.get('user_team_create') !== undefined; + } + + saveSelectionAsTeam(teamName){ + var userIds = []; + this.getSharedUsers().map(function(e){ + if(e.TYPE == 'user') userIds.push(e.ID); + }); + PydioApi.getClient().request({ + get_action:'user_team_create', + team_label:teamName, + 'user_ids[]':userIds + }, function(){ + // Flatten Team? + }); + } + + /**********************************************/ + /* GLOBAL PARAMETERS : label, desc, notif */ + /**********************************************/ + getGlobal(name){ + if(this._pendingData[name] !== undefined){ + return this._pendingData[name]; + } + if(name == 'watch') { + return this._data["element_watch"] == 'META_WATCH_BOTH'; + }else{ + return this._data[name]; + } + } + setGlobal(name, value){ + this._pendingData[name] = value; + this._setStatus('modified'); + } + _globalsAsParameters(params){ + params['repo_label'] = this.getGlobal("label"); + params['repo_description'] = this.getGlobal("description"); + params['self_watch_folder'] = this.getGlobal("watch") ? 'true' : 'false'; + } + + /**************************/ + /* SHARE VISIBILITY */ + /**************************/ + isPublic(){ + if(this._pendingData["scope"] !== undefined){ + return this._pendingData["scope"]; + } + return this._data["share_scope"] == 'public'; + } + toggleVisibility(){ + this._pendingData['scope'] = !this.isPublic(); + this._setStatus('modified'); + } + getShareOwner(){ + return this._data['share_owner']; + } + setNewShareOwner(owner){ + this._pendingData['new_owner'] = owner; + this.save(); + } + _visibilityDataToParameters(params){ + params['share_scope'] = this.isPublic() ? 'public' : 'private'; + if(this._pendingData['new_owner'] && this._pendingData['new_owner'] != this._data['owner']){ + params['transfer_owner'] = this._pendingData['new_owner']; + } + } + + + /****************************/ + /* PUBLIC LINK PASSWORD */ + /****************************/ + hasHiddenPassword(){ + return this._data['has_password']; + } + getPassword(){ + if(this._pendingData['minisite'] && this._pendingData['minisite']['password']){ + return this._pendingData['minisite']['password']; + } + return ''; + } + updatePassword(newValue){ + this._initPendingData(); + this._pendingData['minisite']['password'] = newValue; + this._setStatus('modified'); + } + resetPassword(){ + this._data['has_password'] = false; + this._data['password_cleared'] = true; + this.updatePassword(''); + } + + _passwordAsParameter(params){ + if(this._pendingData['minisite'] && this._pendingData['minisite']['password']){ + params['guest_user_pass'] = this._pendingData['minisite']['password']; + }else if(this._data['password_cleared']){ + params['guest_user_pass'] = ''; + } + } + + /****************************/ + /* PUBLIC LINK EXPIRATION */ + /****************************/ + getExpirationFor(name){ + if(this._pendingData['minisite'] && this._pendingData['minisite']['expiration'][name] !== undefined){ + return this._pendingData['minisite']['expiration'][name]; + } + var current; var defaults={days:0, downloads:0}; + if(this._data['minisite']){ + if(name == 'days'){ + current = this._data['expire_after']; + }else if(name == 'downloads'){ + current = this._data['download_limit']; + } + }else{ + current = defaults[name]; + } + return current; + } + + setExpirationFor(name, value){ + this._initPendingData(); + this._pendingData['minisite']['expiration'][name] = value; + this._setStatus('modified'); + } + + _expirationsToParameters(params){ + if(this.getExpirationFor('days')) params['expiration'] = this.getExpirationFor('days'); + if(this.getExpirationFor('downloads')) params['downloadlimit'] = this.getExpirationFor('downloads'); + } + + + /****************************/ + /* PUBLIC LINKS PERMISSIONS */ + /****************************/ + getPublicLinkPermission(name){ + if(this._pendingData['minisite'] && this._pendingData['minisite']['permissions'][name] !== undefined){ + return this._pendingData['minisite']['permissions'][name]; + } + var current; + var defaults = { + read : (!this._previewEditors || this._previewEditors.length > 0), + download: true, + write:false + }; + if(this._data['minisite']){ + var json = this._data; + if(name == 'download'){ + current = ! json['minisite']['disable_download']; + }else if(name == 'read'){ + current = (json.entries[0].RIGHT.indexOf('r') !== -1 && json['minisite_layout']!='ajxp_unique_dl'); + }else if(name == 'write'){ + current = (json.entries[0].RIGHT.indexOf('w') !== -1); + } + }else{ + current = defaults[name]; + } + return current; + } + + isPublicLinkPreviewDisabled(){ + return (this._previewEditors && this._previewEditors.length == 0); + } + + setPublicLinkPermission(name, value){ + this._initPendingData(); + this._pendingData['minisite']['permissions'][name] = value; + this._setStatus('modified'); + } + + _permissionsToParameters(params){ + if(this.getPublicLinkPermission('read')){ + params['simple_right_read'] = 'on'; + } + if(this.getPublicLinkPermission('download')){ + params['simple_right_download'] = 'on'; + } + if(this.getPublicLinkPermission('write')){ + params['simple_right_write'] = 'on'; + } + } + + /****************************/ + /* PUBLIC LINKS TEMPLATE */ + /****************************/ + getTemplate(){ + if(this._pendingData["minisite"] && this._pendingData["minisite"]["layout"]){ + return this._pendingData["minisite"]["layout"]; + } + if(this._node.isLeaf()){ + if(this.getPublicLinkPermission('read')){ + this._data['minisite_layout'] = 'ajxp_unique_preview'; + }else{ + this._data['minisite_layout'] = 'ajxp_unique_dl'; + } + } + if(this._data['minisite_layout']){ + return this._data['minisite_layout']; + } + } + + setTemplate(tplName){ + this._initPendingData(); + this._pendingData["minisite"]["layout"] = tplName; + this._setStatus('modified'); + } + + _templateToParameter(params){ + if(this.getTemplate()){ + params['minisite_layout'] = this.getTemplate(); + } + } + + /**********************/ + /* CUSTOM LINK HANDLE */ + /**********************/ + updateCustomLink(newValue){ + this._initPendingData(); + this._pendingData['minisite']['custom_link'] = newValue; + this.save(); + } + + /*********************************/ + /* GENERIC: STATUS / LOAD / SAVE */ + /*********************************/ + _setStatus(status){ + this._status = status; + this.notify('status_changed', { + status: status, + model: this + }); + } + + load(){ + if(this._status == 'loading') return; + this._setStatus('loading'); + ShareModel.loadSharedElementData(this._node, function(transport){ + this._data = transport.responseJSON; + this._pendingData = {}; + this._setStatus('idle'); + }.bind(this)); + } + + save(){ + if(Object.keys(this._pendingData).length){ + this.submitToServer(); + } + } + + stopSharing(){ + var params = {get_action:'unshare'}; + ShareModel.prepareShareActionParameters(this.getNode(), params); + PydioApi.getClient().request(params, this.load.bind(this), null); + } + + submitToServer(){ + var params = { + get_action:'share', + sub_action:'share_node', + return_json:'true' + }; + if(this._pendingData["enable_public_link"] !== undefined){ + if(this._pendingData["enable_public_link"]) { + params["enable_public_link"] = "true"; + } else if(this._data["minisite"]){ + params["disable_public_link"] = this._data["minisite"]["hash"]; + } + }else if(this._data["minisite"]){ + params["enable_public_link"] = "true"; + } + params['repo_label'] = this._node.getLabel(); + params["file"] = this._node.getPath(); + if(this._data['repositoryId']){ + params['repository_id'] = this._data['repositoryId']; + }else{ + params["element_type"] = this._node.isLeaf() ? "file" : this._node.getMetadata().get("ajxp_shared_minisite")? "minisite" : "repository"; + params['create_guest_user'] = 'true'; + } + if(this._data.minisite){ + params['guest_user_id'] = this._data.entries[0].ID; + params['hash'] = this._data.minisite.hash; + } + this._globalsAsParameters(params); + this._permissionsToParameters(params); + this._expirationsToParameters(params); + this._passwordAsParameter(params); + this._templateToParameter(params); + this._visibilityDataToParameters(params); + this._sharedUsersToParameters(params); + if(this._pendingData && this._pendingData['minisite'] && this._pendingData['minisite']['custom_link']){ + params['custom_handle'] = this._pendingData['minisite']['custom_link']; + } + PydioApi.getClient().request(params, function(transport){ + var _data = transport.responseJSON; + if(_data !== null){ + this._data = _data; + this._pendingData = {}; + this._setStatus('saved'); + }else{ + // There must have been an error, revert + } + }.bind(this), null); + } + + static prepareShareActionParameters(uniqueNode, params){ + var meta = uniqueNode.getMetadata(); + if(meta.get('shared_element_hash')){ + params["hash"] = meta.get('shared_element_hash'); + params["tmp_repository_id"] = meta.get('shared_element_parent_repository'); + params["element_type"] = meta.get('share_type'); + }else{ + params["file"] = uniqueNode.getPath(); + params["element_type"] = uniqueNode.isLeaf() ? "file" : meta.get("ajxp_shared_minisite")? "minisite" : "repository"; + } + } + + static loadSharedElementData(node, completeCallback=null, errorCallback=null, settings={}){ + var meta = node.getMetadata(); + var options = { + get_action : 'load_shared_element_data', + merged : 'true' + }; + if(meta.get('shared_element_hash')){ + options["hash"] = meta.get('shared_element_hash'); + options["tmp_repository_id"] = meta.get('shared_element_parent_repository'); + options["element_type"] = meta.get('share_type'); + }else{ + options["file"] = node.getPath(); + options["element_type"] = node.isLeaf() ? "file" : meta.get("ajxp_shared_minisite")? "minisite" : "repository"; + } + PydioApi.getClient().request(options, completeCallback, errorCallback, settings); + } + + static getAuthorizations(pydio){ + var pluginConfigs = pydio.getPluginConfigs("action.share"); + var authorizations = { + folder_public_link : pluginConfigs.get("ENABLE_FOLDER_SHARING") == 'both' || pluginConfigs.get("ENABLE_FOLDER_SHARING") == 'minisite' , + folder_workspaces : pluginConfigs.get("ENABLE_FOLDER_SHARING") == 'both' || pluginConfigs.get("ENABLE_FOLDER_SHARING") == 'workspace' , + file_public_link : pluginConfigs.get("ENABLE_FILE_PUBLIC_LINK"), + file_workspaces : true, //pluginConfigs.get("ENABLE_FILE_SHARING"), + editable_hash : pluginConfigs.get("HASH_USER_EDITABLE"), + pass_mandatory: false + }; + var pass_mandatory = pluginConfigs.get("SHARE_FORCE_PASSWORD"); + if(pass_mandatory){ + authorizations.password_mandatory = true; + } + authorizations.password_placeholder = pass_mandatory ? pydio.MessageHash['share_center.176'] : pydio.MessageHash['share_center.148']; + return authorizations; + } + + static compileLayoutData(pydio, node){ + + // Search registry for template nodes starting with minisite_ + var tmpl; + if(node.isLeaf()){ + var currentExt = node.getAjxpMime(); + tmpl = XPathSelectNodes(pydio.getXmlRegistry(), "//template[contains(@name, 'unique_preview_')]"); + }else{ + tmpl = XPathSelectNodes(pydio.getXmlRegistry(), "//template[contains(@name, 'minisite_')]"); + } + + if(!tmpl.length){ + return []; + } + if(tmpl.length == 1){ + return [{LAYOUT_NAME:tmpl[0].getAttribute('element'), LAYOUT_LABEL:''}]; + } + var crtTheme = ajxpBootstrap.parameters.get('theme'); + var values = []; + var noEditorsFound = false; + tmpl.map(function(node){ + var theme = node.getAttribute('theme'); + if(theme && theme != crtTheme) return; + var element = node.getAttribute('element'); + var name = node.getAttribute('name'); + var label = node.getAttribute('label'); + if(currentExt && name == "unique_preview_file"){ + var editors = pydio.Registry.findEditorsForMime(currentExt); + if(!editors.length || (editors.length == 1 && editors[0].editorClass == "OtherEditorChooser")) { + noEditorsFound = true; + return; + } + } + if(label) { + if(MessageHash[label]) label = MessageHash[label]; + }else{ + label = node.getAttribute('name'); + } + values[name] = element; + //chooser.insert(new Element('option', {value:element}).update(label)); + values.push({LAYOUT_NAME:name, LAYOUT_ELEMENT:element, LAYOUT_LABEL: label}); + }); + return values; + /* + var read; + if(node.isLeaf() && linkRightsToTemplates && values["unique_preview_file"] && values["unique_preview_download"]){ + read = oForm.down("#simple_right_read"); + var download = oForm.down("#simple_right_download"); + var observer = function(){ + if(!read.checked && !download.checked){ + download.checked = true; + } + if(read.checked){ + chooser.setValue(values["unique_preview_file"]); + }else{ + chooser.setValue(values["unique_preview_download"]); + } + }; + read.observe("click", observer); + download.observe("click", observer); + + }else if(noEditorsFound){ + read = oForm.down("#simple_right_read"); + read.checked = false; + read.disabled = true; + read.next("label").insert(" (no preview for this file)"); + } + return chooser; + + */ + + + } + + } + + var ReactModel = global.ReactModel || {}; + ReactModel['Share'] = ShareModel; + global.ReactModel = ReactModel; + // Set for dependencies management + global.ReactModelShare = ShareModel; + + +})(window); \ No newline at end of file