diff --git a/apps/common/mobile/lib/controller/Collaboration.jsx b/apps/common/mobile/lib/controller/Collaboration.jsx new file mode 100644 index 000000000..59f310d38 --- /dev/null +++ b/apps/common/mobile/lib/controller/Collaboration.jsx @@ -0,0 +1,26 @@ +import React, { useState } from 'react' +import { resetUsers } from '../store/actions/actions.js' + +const Collaboration = () => { + const onChangeEditUsers = (users) => { + const store = Common.Store.get(); + store.dispatch(resetUsers(Object.values(users))); + }; + + return { + setApi(api) { + this.api = api; + this.api.asc_registerCallback('asc_onAuthParticipantsChanged', onChangeEditUsers); + this.api.asc_registerCallback('asc_onParticipantsChanged', onChangeEditUsers); + // this.api.asc_registerCallback('asc_onAddComment', _.bind(this.onApiAddComment, this)); + // this.api.asc_registerCallback('asc_onAddComments', _.bind(this.onApiAddComments, this)); + // this.api.asc_registerCallback('asc_onChangeCommentData', _.bind(this.onApiChangeCommentData, this)); + // this.api.asc_registerCallback('asc_onRemoveComment', _.bind(this.onApiRemoveComment, this)); + // this.api.asc_registerCallback('asc_onRemoveComments', _.bind(this.onApiRemoveComments, this)); + // this.api.asc_registerCallback('asc_onShowComment', _.bind(this.apiShowComments, this)); + // this.api.asc_registerCallback('asc_onHideComment', _.bind(this.apiHideComments, this)); + } + } +}; + +export {Collaboration as CollaborationController} \ No newline at end of file diff --git a/apps/common/mobile/lib/store/actions/actions.js b/apps/common/mobile/lib/store/actions/actions.js new file mode 100644 index 000000000..258592963 --- /dev/null +++ b/apps/common/mobile/lib/store/actions/actions.js @@ -0,0 +1,8 @@ +export const RESET_USERS = 'RESET_USERS'; + +export const resetUsers = list => { + return { + type: RESET_USERS, + payload: list + } +}; diff --git a/apps/common/mobile/lib/store/users.js b/apps/common/mobile/lib/store/users.js new file mode 100644 index 000000000..3f38e433b --- /dev/null +++ b/apps/common/mobile/lib/store/users.js @@ -0,0 +1,11 @@ +import * as actionTypes from './actions/actions' + +const usersReducer = (state = [], action) => { + if (action.type == actionTypes.RESET_USERS) { + return [...action.payload]; + } + + return state; +}; + +export default usersReducer \ No newline at end of file diff --git a/apps/common/mobile/lib/view/Collaboration.jsx b/apps/common/mobile/lib/view/Collaboration.jsx new file mode 100644 index 000000000..01dda0a47 --- /dev/null +++ b/apps/common/mobile/lib/view/Collaboration.jsx @@ -0,0 +1,81 @@ +import React, { Component } from 'react'; +import { useSelector } from 'react-redux'; +import { Popover, List, ListItem, Navbar, NavTitle, NavRight } from 'framework7-react'; +import { Sheet, Toolbar, BlockTitle, Link, Page, View, Icon } from 'framework7-react'; +import { withTranslation, useTranslation } from 'react-i18next'; + +const PageUsers = () => { + const { t } = useTranslation(); + const userlist = useSelector(state => state.users); + return ( + + + {t("Collaboration.textEditUser")} + + {userlist.map((model, i) => ( + + + + ))} + + ) +}; + +const PageCollaboration = () => { + "use strict"; + + return + + + Close + + + + + + + ; + +}; + +class CollaborationPopover extends Component { + constructor(props) { + super(props); + } + render() { + return ( + + + + + + + + + + ) + } +} + +class CollaborationSheet extends Component { + constructor(props) { + super(props); + + this.routes = [ + {path: '/', component: 'PageCollaboration'}, + {path: '/users/', component: 'PageUsers'} + ]; + } + render() { + return ( + + + + + + ) + } +} + +// export withTranslation()(CollaborationPopover); +export {CollaborationPopover, CollaborationSheet, PageCollaboration, PageUsers, } \ No newline at end of file diff --git a/apps/common/mobile/resources/less/collaboration.less b/apps/common/mobile/resources/less/collaboration.less new file mode 100644 index 000000000..b7429dc4d --- /dev/null +++ b/apps/common/mobile/resources/less/collaboration.less @@ -0,0 +1,5 @@ +.coauth__list__icon { + width: 20px; + height: 20px; + border-radius: 10px; +} \ No newline at end of file diff --git a/apps/documenteditor/mobile/locale/en.json b/apps/documenteditor/mobile/locale/en.json index 5ed494bf4..ec605c06e 100644 --- a/apps/documenteditor/mobile/locale/en.json +++ b/apps/documenteditor/mobile/locale/en.json @@ -10,5 +10,8 @@ "textDocumentInfo": "Document Info", "textHelp": "Help", "textAbout": "About" - } + }, + "Collaboration": { + "textEditUser": "Users who are editing the file:" + } } \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/components/app.jsx b/apps/documenteditor/mobile/src/components/app.jsx index d1fecfc46..cea2bab65 100644 --- a/apps/documenteditor/mobile/src/components/app.jsx +++ b/apps/documenteditor/mobile/src/components/app.jsx @@ -27,6 +27,7 @@ import routes from '../js/routes'; import '../../../../common/Gateway.js'; import '../../../../common/main/lib/util/utils.js'; +import { CollaborationController } from '../../../../common/mobile/lib/controller/Collaboration.jsx'; export default class extends React.Component { constructor() { @@ -140,8 +141,8 @@ export default class extends React.Component { let me = this; console.log('load config'); - me.editorConfig = Object.assign({}, this.editorConfig, data); - // me.appOptions.user = Common.Utils.fillUserInfo(me.editorConfig.user, me.editorConfig.lang, "Local.User"/*me.textAnonymous*/); + me.editorConfig = Object.assign({}, this.editorConfig, data.config); + me.appOptions.user = Common.Utils.fillUserInfo(me.editorConfig.user, me.editorConfig.lang, "Local.User"/*me.textAnonymous*/); }; const loadDocument = data => { @@ -155,8 +156,8 @@ export default class extends React.Component { let _permissions = Object.assign({}, data.doc.permissions), _user = new Asc.asc_CUserInfo(); - // _user.put_Id(this.appOptions.user.id); - // _user.put_FullName(this.appOptions.user.fullname); + _user.put_Id(this.appOptions.user.id); + _user.put_FullName(this.appOptions.user.fullname); docInfo = new Asc.asc_CDocInfo(); docInfo.put_Id(data.doc.key); @@ -242,6 +243,11 @@ export default class extends React.Component { // Common.Gateway.on('showmessage', _.bind(me.onExternalMessage, me)); Common.Gateway.on('opendocument', loadDocument); Common.Gateway.appReady(); + + Common.Controllers = {}; + Common.Controllers.Collaboration = new CollaborationController(); + Common.Controllers.Collaboration.setApi(this.api, ""); + }, error => { console.log('promise failed ' + error); }); @@ -253,4 +259,4 @@ export default class extends React.Component { document.body.appendChild(script); } -} \ No newline at end of file +} diff --git a/apps/documenteditor/mobile/src/css/app.less b/apps/documenteditor/mobile/src/css/app.less index 5630d0059..98c60ef58 100644 --- a/apps/documenteditor/mobile/src/css/app.less +++ b/apps/documenteditor/mobile/src/css/app.less @@ -1,3 +1,6 @@ + +@import '../../../../common/mobile/resources/less/collaboration.less'; + /* Left Panel right border when it is visible by breakpoint */ .panel-left.panel-in-breakpoint:before { position: absolute; diff --git a/apps/documenteditor/mobile/src/js/app.js b/apps/documenteditor/mobile/src/js/app.js index 7c5a51a53..403dbd18c 100644 --- a/apps/documenteditor/mobile/src/js/app.js +++ b/apps/documenteditor/mobile/src/js/app.js @@ -24,15 +24,20 @@ import App from '../components/app.jsx'; import { I18nextProvider } from 'react-i18next'; import i18n from './i18n'; +import { Provider } from 'react-redux' +import { store } from '../store/store.js' + // Init F7 React Plugin Framework7.use(Framework7React) // Mount React App ReactDOM.render( - - - + + + + + , document.getElementById('app'), ); \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/js/routes.js b/apps/documenteditor/mobile/src/js/routes.js index 5725f5d4a..cefa3d19b 100644 --- a/apps/documenteditor/mobile/src/js/routes.js +++ b/apps/documenteditor/mobile/src/js/routes.js @@ -9,6 +9,8 @@ import LeftPage2 from '../pages/left-page-2.jsx'; import DynamicRoutePage from '../pages/dynamic-route.jsx'; import RequestAndLoad from '../pages/request-and-load.jsx'; +import { PageCollaboration, PageUsers } from '../../../../common/mobile/lib/view/Collaboration.jsx'; + var routes = [ { path: '/', @@ -18,6 +20,14 @@ var routes = [ path: '/document-settings/', component: DocumentSettings, }, + { + path: '/users/', + component: PageUsers + }, + { + path: '/collab-main/', + component: PageCollaboration + }, { path: '/margins/', component: Margins, diff --git a/apps/documenteditor/mobile/src/pages/home.jsx b/apps/documenteditor/mobile/src/pages/home.jsx index 07bdf0513..fbe35436a 100644 --- a/apps/documenteditor/mobile/src/pages/home.jsx +++ b/apps/documenteditor/mobile/src/pages/home.jsx @@ -21,6 +21,7 @@ import { import EditPopup from '../components/edit/Edit.jsx'; import SettingsPopup from '../components/settings/Settings.jsx'; +import { CollaborationPopover, CollaborationSheet } from '../../../../common/mobile/lib/view/Collaboration.jsx' export default class Home extends Component { constructor(props) { @@ -39,6 +40,8 @@ export default class Home extends Component { Edit + {/*Users*/} + Users Settings @@ -47,6 +50,8 @@ export default class Home extends Component { + + ) } diff --git a/apps/documenteditor/mobile/src/store/reducers/root.js b/apps/documenteditor/mobile/src/store/reducers/root.js new file mode 100644 index 000000000..7a876a0d0 --- /dev/null +++ b/apps/documenteditor/mobile/src/store/reducers/root.js @@ -0,0 +1,10 @@ +import { combineReducers } from 'redux'; +import usersReducer from '../../../../../common/mobile/lib/store/users' + +export const initialState = { + users: [] +}; + +export const rootReducer = combineReducers({ + users: usersReducer +}); \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/store/store.js b/apps/documenteditor/mobile/src/store/store.js new file mode 100644 index 000000000..93f91abca --- /dev/null +++ b/apps/documenteditor/mobile/src/store/store.js @@ -0,0 +1,9 @@ +import { createStore } from 'redux' +import { rootReducer, initialState } from './reducers/root' + +const store = createStore(rootReducer, initialState); + +!window.Common && (window.Common = {}); +Common.Store = { get: () => store }; + +export { store }; \ No newline at end of file diff --git a/build/package.json b/build/package.json index 067b7253d..44961d8c8 100644 --- a/build/package.json +++ b/build/package.json @@ -4,7 +4,6 @@ "homepage": "http://www.onlyoffice.com", "private": true, "dependencies": { - "chai": "1.9.1", "grunt": "^1.0.0", "grunt-contrib-clean": "^1.0.0", "grunt-contrib-concat": "^0.5.1", @@ -17,15 +16,18 @@ "grunt-contrib-uglify": "^4.0.1", "grunt-inline": "0.3.4", "grunt-json-minify": "^1.1.0", - "grunt-mocha": "^1.0.0", "grunt-spritesmith": "^6.8.0", "grunt-svgmin": "^6.0.0", "grunt-text-replace": "0.3.11", "iconsprite": "file:sprites", "iconv-lite": "^0.5.1", "less-plugin-clean-css": "1.5.0", - "lodash": "^4.0.0", - "mocha": "^6.2.2", + "lodash": "^4.17.20", "vinyl-fs": "^3.0.3" + }, + "devDependencies": { + "chai": "1.9.1", + "mocha": "^6.2.2", + "grunt-mocha": "^1.0.0" } } diff --git a/vendor/framework7-react/build/webpack.config.js b/vendor/framework7-react/build/webpack.config.js index d3d2672a1..c2335c70e 100644 --- a/vendor/framework7-react/build/webpack.config.js +++ b/vendor/framework7-react/build/webpack.config.js @@ -64,6 +64,7 @@ module.exports = { }, include: [ resolvePath('../../apps/documenteditor/mobile/src'), + resolvePath('../../apps/common/mobile/lib'), resolvePath('node_modules/framework7'), resolvePath('node_modules/framework7-react'), @@ -106,6 +107,7 @@ module.exports = { } }), 'css-loader', + 'less-loader', { loader: 'postcss-loader', options: { diff --git a/vendor/framework7-react/package.json b/vendor/framework7-react/package.json index 564f94bf2..50bec7d9a 100644 --- a/vendor/framework7-react/package.json +++ b/vendor/framework7-react/package.json @@ -56,6 +56,8 @@ "ora": "^4.0.5", "postcss-loader": "^3.0.0", "postcss-preset-env": "^6.7.0", + "react-redux": "^7.2.1", + "redux": "^4.0.5", "rimraf": "^3.0.2", "style-loader": "^1.2.1", "terser-webpack-plugin": "^3.1.0",