1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-07-07 20:19:34 +00:00

Update react version 3 (#7453)

* update react version

* update reactstrap

* optimize code

* update react-select version

* update react-responsive

* update react-chartjs version

* update qrocde version

* update seafile-editor version

* update tldraw editor version

* fix code bug
This commit is contained in:
杨顺强 2025-02-14 14:04:25 +08:00 committed by GitHub
parent ef7ac1dd8b
commit ccab6f1552
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
112 changed files with 2301 additions and 1357 deletions

File diff suppressed because it is too large Load Diff

View File

@ -8,19 +8,19 @@
"@codemirror/view": "^6.34.1", "@codemirror/view": "^6.34.1",
"@emoji-mart/data": "^1.2.1", "@emoji-mart/data": "^1.2.1",
"@emoji-mart/react": "^1.1.1", "@emoji-mart/react": "^1.1.1",
"@gatsbyjs/reach-router": "1.3.9", "@gatsbyjs/reach-router": "2.0.1",
"@seafile/react-image-lightbox": "3.0.4", "@seafile/react-image-lightbox": "4.0.0",
"@seafile/resumablejs": "1.1.16", "@seafile/resumablejs": "1.1.16",
"@seafile/sdoc-editor": "1.0.217", "@seafile/sdoc-editor": "1.0.217",
"@seafile/seafile-calendar": "0.0.28", "@seafile/seafile-calendar": "0.0.28",
"@seafile/seafile-editor": "1.0.133", "@seafile/seafile-editor": "2.0.0",
"@seafile/sf-metadata-ui-component": "^0.0.68", "@seafile/sf-metadata-ui-component": "^0.0.64",
"@seafile/stldraw-editor": "0.1.5", "@seafile/stldraw-editor": "1.0.0",
"@uiw/codemirror-extensions-langs": "^4.19.4", "@uiw/codemirror-extensions-langs": "^4.19.4",
"@uiw/codemirror-themes": "^4.23.5", "@uiw/codemirror-themes": "^4.23.5",
"@uiw/react-codemirror": "^4.19.4", "@uiw/react-codemirror": "^4.19.4",
"axios": "^1.7.4", "axios": "^1.7.4",
"chart.js": "3.6.0", "chart.js": "4.4.7",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"codemirror": "^6.0.1", "codemirror": "^6.0.1",
"copy-to-clipboard": "^3.0.8", "copy-to-clipboard": "^3.0.8",
@ -35,19 +35,19 @@
"MD5": "^1.3.0", "MD5": "^1.3.0",
"object-assign": "4.1.1", "object-assign": "4.1.1",
"prop-types": "^15.8.1", "prop-types": "^15.8.1",
"qrcode.react": "^1.0.1", "qrcode.react": "4.2.0",
"react": "17.0.2", "react": "18.3.1",
"react-app-polyfill": "^2.0.0", "react-app-polyfill": "^2.0.0",
"react-chartjs-2": "4.0.0", "react-chartjs-2": "5.3.0",
"react-cookies": "^0.1.0", "react-cookies": "^0.1.0",
"react-dnd": "^2.6.0", "react-dnd": "^2.6.0",
"react-dnd-html5-backend": "^2.6.0", "react-dnd-html5-backend": "^2.6.0",
"react-dom": "17.0.2", "react-dom": "18.3.1",
"react-i18next": "^10.12.2", "react-i18next": "^10.12.2",
"react-responsive": "9.0.2", "react-responsive": "10.0.0",
"react-select": "5.7.0", "react-select": "5.9.0",
"react-transition-group": "4.4.5", "react-transition-group": "4.4.5",
"reactstrap": "8.9.0", "reactstrap": "9.2.3",
"socket.io-client": "^2.2.0", "socket.io-client": "^2.2.0",
"svg-sprite-loader": "^6.0.11", "svg-sprite-loader": "^6.0.11",
"svgo-loader": "^3.0.1", "svgo-loader": "^3.0.1",
@ -63,7 +63,7 @@
"start": "node scripts/start.js", "start": "node scripts/start.js",
"build": "node scripts/build.js", "build": "node scripts/build.js",
"test": "node scripts/test.js --env=jsdom", "test": "node scripts/test.js --env=jsdom",
"dev": "export NODE_ENV=development && node config/server.js" "dev": "export NODE_ENV=development && node --max-old-space-size=4096 config/server.js"
}, },
"browserslist": { "browserslist": {
"production": [ "production": [

View File

@ -1,6 +1,6 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import { Router, navigate } from '@gatsbyjs/reach-router'; import { Router, navigate, LocationProvider, globalHistory } from '@gatsbyjs/reach-router';
import MediaQuery from 'react-responsive'; import MediaQuery from 'react-responsive';
import { Modal } from 'reactstrap'; import { Modal } from 'reactstrap';
import { siteRoot, siteTitle, mediaUrl, faviconPath } from './utils/constants'; import { siteRoot, siteTitle, mediaUrl, faviconPath } from './utils/constants';
@ -374,4 +374,9 @@ class App extends Component {
} }
} }
ReactDom.render(<App />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(
<LocationProvider history={globalHistory}>
<App />
</LocationProvider>
);

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import QRCode from 'qrcode.react'; import { QRCodeSVG } from 'qrcode.react';
import { Button, Popover, PopoverBody } from 'reactstrap'; import { Button, Popover, PopoverBody } from 'reactstrap';
import { gettext } from '../utils/constants'; import { gettext } from '../utils/constants';
@ -34,7 +34,7 @@ class ButtonQR extends React.Component {
<Button outline color="primary" className="btn-icon btn-qr-code-icon sf3-font sf3-font-qr-code" id={this.btnID} onClick={this.togglePopover} type="button"></Button> <Button outline color="primary" className="btn-icon btn-qr-code-icon sf3-font sf3-font-qr-code" id={this.btnID} onClick={this.togglePopover} type="button"></Button>
<Popover placement="bottom" isOpen={isPopoverOpen} target={this.btnID} toggle={this.togglePopover}> <Popover placement="bottom" isOpen={isPopoverOpen} target={this.btnID} toggle={this.togglePopover}>
<PopoverBody> <PopoverBody>
<QRCode value={link} size={128} /> <QRCodeSVG value={link} size={128} />
<p className="m-0 mt-1 text-center" style={{ 'maxWidth': '128px' }}>{gettext('Scan the QR code to view the shared content directly')}</p> <p className="m-0 mt-1 text-center" style={{ 'maxWidth': '128px' }}>{gettext('Scan the QR code to view the shared content directly')}</p>
</PopoverBody> </PopoverBody>
</Popover> </Popover>

View File

@ -1,6 +1,6 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import ReactDOM from 'react-dom'; import { findDOMNode } from 'react-dom';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import { siteRoot, isPro, gettext, appAvatarURL, enableSSOToThirdpartWebsite } from '../../utils/constants'; import { siteRoot, isPro, gettext, appAvatarURL, enableSSOToThirdpartWebsite } from '../../utils/constants';
@ -36,7 +36,7 @@ class Account extends Component {
} }
getContainer = () => { getContainer = () => {
return ReactDOM.findDOMNode(this); return findDOMNode(this);
}; };
handleProps = () => { handleProps = () => {

View File

@ -228,7 +228,7 @@ class ContextMenu extends React.Component {
onMouseMove={(e) => {e.stopPropagation();}} onMouseMove={(e) => {e.stopPropagation();}}
> >
<DropdownToggle <DropdownToggle
tag='div' tag='span'
className="dropdown-item font-weight-normal rounded-0 d-flex align-items-center" className="dropdown-item font-weight-normal rounded-0 d-flex align-items-center"
onMouseEnter={this.toggleSubMenuShown.bind(this, menuItem)} onMouseEnter={this.toggleSubMenuShown.bind(this, menuItem)}
> >

View File

@ -144,7 +144,7 @@ class DirTool extends React.Component {
aria-expanded={isDropdownMenuOpen} aria-expanded={isDropdownMenuOpen}
> >
</DropdownToggle> </DropdownToggle>
<DropdownMenu right={true}> <DropdownMenu>
{menuItems.map((menuItem, index) => { {menuItems.map((menuItem, index) => {
if (menuItem === 'Divider') { if (menuItem === 'Divider') {
return <DropdownItem key={index} divider />; return <DropdownItem key={index} divider />;

View File

@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import copy from 'copy-to-clipboard'; import copy from 'copy-to-clipboard';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { Button, Form, FormGroup, Label, Input, InputGroup, InputGroupAddon, Alert } from 'reactstrap'; import { Button, Form, FormGroup, Label, Input, InputGroup, Alert } from 'reactstrap';
import { gettext, shareLinkForceUsePassword, shareLinkPasswordMinLength, shareLinkPasswordStrengthLevel, canSendShareLinkEmail, uploadLinkExpireDaysMin, uploadLinkExpireDaysMax, uploadLinkExpireDaysDefault } from '../../utils/constants'; import { gettext, shareLinkForceUsePassword, shareLinkPasswordMinLength, shareLinkPasswordStrengthLevel, canSendShareLinkEmail, uploadLinkExpireDaysMin, uploadLinkExpireDaysMax, uploadLinkExpireDaysDefault } from '../../utils/constants';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
@ -300,14 +300,12 @@ class GenerateUploadLink extends React.Component {
<Input type="text" readOnly={true} value={sharedUploadInfo.password} /> : <Input type="text" readOnly={true} value={sharedUploadInfo.password} /> :
<Input type="text" readOnly={true} value={'***************'} /> <Input type="text" readOnly={true} value={'***************'} />
} }
<InputGroupAddon addonType="append">
<Button <Button
aria-label={this.state.storedPasswordVisible ? gettext('Hide') : gettext('Show')} aria-label={this.state.storedPasswordVisible ? gettext('Hide') : gettext('Show')}
onClick={this.toggleStoredPasswordVisible} onClick={this.toggleStoredPasswordVisible}
className={`link-operation-icon eye-icon sf3-font sf3-font-eye${this.state.storedPasswordVisible ? '' : '-slash'}`} className={`link-operation-icon eye-icon sf3-font sf3-font-eye${this.state.storedPasswordVisible ? '' : '-slash'}`}
> >
</Button> </Button>
</InputGroupAddon>
</InputGroup> </InputGroup>
</dd> </dd>
</> </>
@ -338,7 +336,6 @@ class GenerateUploadLink extends React.Component {
) : ( ) : (
<InputGroup className="share-link-details-item"> <InputGroup className="share-link-details-item">
<Input type="text" readOnly={true} value={dayjs(sharedUploadInfo.expire_date).format('YYYY-MM-DD HH:mm:ss')} /> <Input type="text" readOnly={true} value={dayjs(sharedUploadInfo.expire_date).format('YYYY-MM-DD HH:mm:ss')} />
<InputGroupAddon addonType="append">
<Button <Button
aria-label={gettext('Edit')} aria-label={gettext('Edit')}
title={gettext('Edit')} title={gettext('Edit')}
@ -346,7 +343,6 @@ class GenerateUploadLink extends React.Component {
onClick={this.editExpirationToggle} onClick={this.editExpirationToggle}
> >
</Button> </Button>
</InputGroupAddon>
</InputGroup> </InputGroup>
)} )}
</dd> </dd>
@ -389,14 +385,12 @@ class GenerateUploadLink extends React.Component {
<span className="tip">{passwordLengthTip}</span> <span className="tip">{passwordLengthTip}</span>
<InputGroup style={{ width: inputWidth }}> <InputGroup style={{ width: inputWidth }}>
<Input id="passwd" type={this.state.passwordVisible ? 'text' : 'password'} value={this.state.password || ''} onChange={this.inputPassword} /> <Input id="passwd" type={this.state.passwordVisible ? 'text' : 'password'} value={this.state.password || ''} onChange={this.inputPassword} />
<InputGroupAddon addonType="append">
<Button onClick={this.togglePasswordVisible}> <Button onClick={this.togglePasswordVisible}>
<i className={`link-operation-icon sf3-font sf3-font-eye${this.state.passwordVisible ? '' : '-slash'}`}></i> <i className={`link-operation-icon sf3-font sf3-font-eye${this.state.passwordVisible ? '' : '-slash'}`}></i>
</Button> </Button>
<Button onClick={this.generatePassword}> <Button onClick={this.generatePassword}>
<i className="link-operation-icon sf3-font sf3-font-magic"></i> <i className="link-operation-icon sf3-font sf3-font-magic"></i>
</Button> </Button>
</InputGroupAddon>
</InputGroup> </InputGroup>
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>

View File

@ -1,6 +1,6 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Button, Input, InputGroup, InputGroupAddon } from 'reactstrap'; import { Button, Input, InputGroup } from 'reactstrap';
import { gettext, isPro, siteRoot } from '../../utils/constants'; import { gettext, isPro, siteRoot } from '../../utils/constants';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
@ -328,7 +328,7 @@ class LibSubFolderSetGroupPermissionDialog extends React.Component {
<td> <td>
<InputGroup> <InputGroup>
<Input value={this.state.folderPath} onChange={this.onSetSubFolder} /> <Input value={this.state.folderPath} onChange={this.onSetSubFolder} />
<InputGroupAddon addonType="append"><Button className="sf2-icon-plus" onClick={this.toggleFileChooser}></Button></InputGroupAddon> <Button className="sf2-icon-plus" onClick={this.toggleFileChooser}></Button>
</InputGroup> </InputGroup>
</td> </td>
} }

View File

@ -1,7 +1,7 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { gettext, isPro, siteRoot } from '../../utils/constants'; import { gettext, isPro, siteRoot } from '../../utils/constants';
import { Button, Input, InputGroup, InputGroupAddon } from 'reactstrap'; import { Button, Input, InputGroup } from 'reactstrap';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
import UserSelect from '../user-select'; import UserSelect from '../user-select';
@ -288,7 +288,7 @@ class LibSubFolderSetUserPermissionDialog extends React.Component {
<td> <td>
<InputGroup> <InputGroup>
<Input value={this.state.folderPath} onChange={this.onSetSubFolder} /> <Input value={this.state.folderPath} onChange={this.onSetSubFolder} />
<InputGroupAddon addonType="append"><Button className="sf2-icon-plus" onClick={this.toggleFileChooser}></Button></InputGroupAddon> <Button className="sf2-icon-plus" onClick={this.toggleFileChooser}></Button>
</InputGroup> </InputGroup>
</td> </td>
} }

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Button, Modal, Input, ModalBody, ModalFooter, Label, Form, InputGroup, InputGroupAddon, FormGroup } from 'reactstrap'; import { Button, Modal, Input, ModalBody, ModalFooter, Label, Form, InputGroup, FormGroup } from 'reactstrap';
import { gettext } from '../../utils/constants'; import { gettext } from '../../utils/constants';
import SeahubModalHeader from '@/components/common/seahub-modal-header'; import SeahubModalHeader from '@/components/common/seahub-modal-header';
@ -146,14 +146,12 @@ class AddOrgUserDialog extends React.Component {
<Label for="userPwd">{gettext('Password')}</Label> <Label for="userPwd">{gettext('Password')}</Label>
<InputGroup className="passwd"> <InputGroup className="passwd">
<Input id="userPwd" innerRef={input => {this.passwdInput = input;}} value={this.state.password || ''} onChange={this.inputPassword} /> <Input id="userPwd" innerRef={input => {this.passwdInput = input;}} value={this.state.password || ''} onChange={this.inputPassword} />
<InputGroupAddon addonType="append">
<Button onClick={this.togglePasswordVisible}> <Button onClick={this.togglePasswordVisible}>
<i className={`link-operation-icon sf3-font sf3-font-eye${this.state.isPasswordVisible ? '-slash' : ''}`}></i> <i className={`link-operation-icon sf3-font sf3-font-eye${this.state.isPasswordVisible ? '-slash' : ''}`}></i>
</Button> </Button>
<Button onClick={this.generatePassword}> <Button onClick={this.generatePassword}>
<i className="link-operation-icon sf3-font sf3-font-magic"></i> <i className="link-operation-icon sf3-font sf3-font-magic"></i>
</Button> </Button>
</InputGroupAddon>
</InputGroup> </InputGroup>
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Button, Modal, ModalBody, ModalFooter, Input, InputGroupAddon, InputGroup } from 'reactstrap'; import { Button, Modal, ModalBody, ModalFooter, Input, InputGroup, InputGroupText } from 'reactstrap';
import { gettext, orgID } from '../../utils/constants'; import { gettext, orgID } from '../../utils/constants';
import SeahubModalHeader from '@/components/common/seahub-modal-header'; import SeahubModalHeader from '@/components/common/seahub-modal-header';
import { orgAdminAPI } from '../../utils/org-admin-api'; import { orgAdminAPI } from '../../utils/org-admin-api';
@ -66,7 +66,7 @@ class SetGroupQuotaDialog extends React.Component {
onChange={this.handleChange} onChange={this.handleChange}
autoFocus={true} autoFocus={true}
/> />
<InputGroupAddon addonType="append">{'MB'}</InputGroupAddon> <InputGroupText addonType="append">{'MB'}</InputGroupText>
</InputGroup> </InputGroup>
<p className="tip"> <p className="tip">
<br/><span>{gettext('An integer that is greater than 0 or equal to -2.')}</span><br/> <br/><span>{gettext('An integer that is greater than 0 or equal to -2.')}</span><br/>

View File

@ -1,6 +1,6 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Modal, ModalBody, ModalFooter, Alert, Button, Input, InputGroup, InputGroupAddon } from 'reactstrap'; import { Modal, ModalBody, ModalFooter, Alert, Button, Input, InputGroup } from 'reactstrap';
import { gettext } from '../../utils/constants'; import { gettext } from '../../utils/constants';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
import SeahubModalHeader from '@/components/common/seahub-modal-header'; import SeahubModalHeader from '@/components/common/seahub-modal-header';
@ -74,14 +74,12 @@ class ResetWebdavPassword extends Component {
<ModalBody> <ModalBody>
<InputGroup> <InputGroup>
<Input type={this.state.isPasswordVisible ? 'text' : 'password'} value={this.state.password} onChange={this.handleInputChange} autoComplete="new-password"/> <Input type={this.state.isPasswordVisible ? 'text' : 'password'} value={this.state.password} onChange={this.handleInputChange} autoComplete="new-password"/>
<InputGroupAddon addonType="append">
<Button onClick={this.togglePasswordVisible}> <Button onClick={this.togglePasswordVisible}>
<i className={`sf3-font sf3-font-eye${this.state.isPasswordVisible ? '' : '-slash'}`}></i> <i className={`sf3-font sf3-font-eye${this.state.isPasswordVisible ? '' : '-slash'}`}></i>
</Button> </Button>
<Button onClick={this.generatePassword}> <Button onClick={this.generatePassword}>
<i className="sf3-font sf3-font-magic"></i> <i className="sf3-font sf3-font-magic"></i>
</Button> </Button>
</InputGroupAddon>
</InputGroup> </InputGroup>
<p className="form-text text-muted m-0">{passwordTip}</p> <p className="form-text text-muted m-0">{passwordTip}</p>
{this.state.errMsg && <Alert color="danger" className="m-0 mt-2">{gettext(this.state.errMsg)}</Alert>} {this.state.errMsg && <Alert color="danger" className="m-0 mt-2">{gettext(this.state.errMsg)}</Alert>}

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Modal, ModalBody, ModalFooter, InputGroup, InputGroupAddon, InputGroupText } from 'reactstrap'; import { Modal, ModalBody, ModalFooter, InputGroup, InputGroupText } from 'reactstrap';
import { gettext } from '../../utils/constants'; import { gettext } from '../../utils/constants';
import { orgAdminAPI } from '../../utils/org-admin-api'; import { orgAdminAPI } from '../../utils/org-admin-api';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
@ -66,9 +66,7 @@ class SetOrgUserDefaultQuota extends React.Component {
<React.Fragment> <React.Fragment>
<InputGroup> <InputGroup>
<input type="text" className="form-control" value={inputValue} onChange={this.handleInputChange} /> <input type="text" className="form-control" value={inputValue} onChange={this.handleInputChange} />
<InputGroupAddon addonType="append">
<InputGroupText>MB</InputGroupText> <InputGroupText>MB</InputGroupText>
</InputGroupAddon>
</InputGroup> </InputGroup>
<p className="small text-secondary mt-2 mb-2">{gettext('Tip: 0 means default limit')}</p> <p className="small text-secondary mt-2 mb-2">{gettext('Tip: 0 means default limit')}</p>
{formErrorMsg && <p className="error m-0 mt-2">{formErrorMsg}</p>} {formErrorMsg && <p className="error m-0 mt-2">{formErrorMsg}</p>}

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Modal, ModalBody, ModalFooter, InputGroup, InputGroupAddon, InputGroupText } from 'reactstrap'; import { Modal, ModalBody, ModalFooter, InputGroup, InputGroupText } from 'reactstrap';
import { gettext } from '../../utils/constants'; import { gettext } from '../../utils/constants';
import { orgAdminAPI } from '../../utils/org-admin-api'; import { orgAdminAPI } from '../../utils/org-admin-api';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
@ -68,9 +68,7 @@ class SetOrgUserQuota extends React.Component {
<React.Fragment> <React.Fragment>
<InputGroup> <InputGroup>
<input type="text" className="form-control" value={inputValue} onChange={this.handleInputChange} /> <input type="text" className="form-control" value={inputValue} onChange={this.handleInputChange} />
<InputGroupAddon addonType="append">
<InputGroupText>MB</InputGroupText> <InputGroupText>MB</InputGroupText>
</InputGroupAddon>
</InputGroup> </InputGroup>
<p className="small text-secondary mt-2 mb-2">{gettext('Tip: 0 means default limit')}</p> <p className="small text-secondary mt-2 mb-2">{gettext('Tip: 0 means default limit')}</p>
{formErrorMsg && <p className="error m-0 mt-2">{formErrorMsg}</p>} {formErrorMsg && <p className="error m-0 mt-2">{formErrorMsg}</p>}

View File

@ -1,6 +1,6 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Modal, ModalBody, ModalFooter, Alert, Button, Input, InputGroup, InputGroupAddon } from 'reactstrap'; import { Modal, ModalBody, ModalFooter, Alert, Button, Input, InputGroup } from 'reactstrap';
import { gettext } from '../../utils/constants'; import { gettext } from '../../utils/constants';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
import SeahubModalHeader from '@/components/common/seahub-modal-header'; import SeahubModalHeader from '@/components/common/seahub-modal-header';
@ -74,14 +74,12 @@ class SetWebdavPassword extends Component {
<ModalBody> <ModalBody>
<InputGroup> <InputGroup>
<Input type={this.state.isPasswordVisible ? 'text' : 'password'} value={this.state.password} onChange={this.handleInputChange} autoComplete="new-password"/> <Input type={this.state.isPasswordVisible ? 'text' : 'password'} value={this.state.password} onChange={this.handleInputChange} autoComplete="new-password"/>
<InputGroupAddon addonType="append">
<Button onClick={this.togglePasswordVisible}> <Button onClick={this.togglePasswordVisible}>
<i className={`sf3-font sf3-font-eye${this.state.isPasswordVisible ? '' : 'slash'}`}></i> <i className={`sf3-font sf3-font-eye${this.state.isPasswordVisible ? '' : 'slash'}`}></i>
</Button> </Button>
<Button onClick={this.generatePassword}> <Button onClick={this.generatePassword}>
<i className="sf3-font sf3-font-magic"></i> <i className="sf3-font sf3-font-magic"></i>
</Button> </Button>
</InputGroupAddon>
</InputGroup> </InputGroup>
<p className="form-text text-muted m-0">{passwordTip}</p> <p className="form-text text-muted m-0">{passwordTip}</p>
{this.state.errMsg && <Alert color="danger" className="m-0 mt-2">{gettext(this.state.errMsg)}</Alert>} {this.state.errMsg && <Alert color="danger" className="m-0 mt-2">{gettext(this.state.errMsg)}</Alert>}

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Modal, ModalBody, ModalFooter, Button, Form, FormGroup, Input, InputGroup, InputGroupAddon, InputGroupText } from 'reactstrap'; import { Modal, ModalBody, ModalFooter, Button, Form, FormGroup, Input, InputGroup, InputGroupText } from 'reactstrap';
import { gettext } from '../../../utils/constants'; import { gettext } from '../../../utils/constants';
import SeahubModalHeader from '@/components/common/seahub-modal-header'; import SeahubModalHeader from '@/components/common/seahub-modal-header';
@ -59,9 +59,7 @@ class SetQuotaDialog extends React.Component {
onKeyDown={this.handleKeyDown} onKeyDown={this.handleKeyDown}
onChange={this.handleQuotaChange} onChange={this.handleQuotaChange}
/> />
<InputGroupAddon addonType="append">
<InputGroupText>MB</InputGroupText> <InputGroupText>MB</InputGroupText>
</InputGroupAddon>
</InputGroup> </InputGroup>
<p className="small text-secondary mt-2 mb-2"> <p className="small text-secondary mt-2 mb-2">
{gettext('An integer that is greater than or equal to 0.')} {gettext('An integer that is greater than or equal to 0.')}

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Modal, ModalBody, ModalFooter, Button, Form, FormGroup, Input, InputGroup, InputGroupAddon, InputGroupText } from 'reactstrap'; import { Modal, ModalBody, ModalFooter, Button, Form, FormGroup, Input, InputGroup, InputGroupText } from 'reactstrap';
import { gettext } from '../../../utils/constants'; import { gettext } from '../../../utils/constants';
import SeahubModalHeader from '@/components/common/seahub-modal-header'; import SeahubModalHeader from '@/components/common/seahub-modal-header';
@ -60,9 +60,7 @@ class SysAdminSetUploadDownloadRateLimitDialog extends React.Component {
onKeyDown={this.handleKeyDown} onKeyDown={this.handleKeyDown}
onChange={this.handleRateLimitChange} onChange={this.handleRateLimitChange}
/> />
<InputGroupAddon addonType="append">
<InputGroupText>kB/s</InputGroupText> <InputGroupText>kB/s</InputGroupText>
</InputGroupAddon>
</InputGroup> </InputGroup>
<p className="small text-secondary mt-2 mb-2"> <p className="small text-secondary mt-2 mb-2">
{gettext('An integer that is greater than or equal to 0.')} {gettext('An integer that is greater than or equal to 0.')}

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Alert, Modal, ModalBody, ModalFooter, Button, Form, FormGroup, Label, Input, InputGroup, InputGroupAddon } from 'reactstrap'; import { Alert, Modal, ModalBody, ModalFooter, Button, Form, FormGroup, Label, Input, InputGroup } from 'reactstrap';
import { gettext } from '../../../utils/constants'; import { gettext } from '../../../utils/constants';
import { Utils } from '../../../utils/utils'; import { Utils } from '../../../utils/utils';
import SysAdminUserRoleEditor from '../../../components/select-editor/sysadmin-user-role-editor'; import SysAdminUserRoleEditor from '../../../components/select-editor/sysadmin-user-role-editor';
@ -154,14 +154,12 @@ class SysAdminAddUserDialog extends React.Component {
<Label>{gettext('Password')}</Label> <Label>{gettext('Password')}</Label>
<InputGroup> <InputGroup>
<Input autoComplete="new-password" type={isPasswordVisible ? 'text' : 'password'} value={password || ''} onChange={this.inputPassword} /> <Input autoComplete="new-password" type={isPasswordVisible ? 'text' : 'password'} value={password || ''} onChange={this.inputPassword} />
<InputGroupAddon addonType="append">
<Button className="mt-0" onClick={this.togglePasswordVisible}> <Button className="mt-0" onClick={this.togglePasswordVisible}>
<i className={`link-operation-icon sf3-font sf3-font-eye${this.state.isPasswordVisible ? '' : '-slash'}`}></i> <i className={`link-operation-icon sf3-font sf3-font-eye${this.state.isPasswordVisible ? '' : '-slash'}`}></i>
</Button> </Button>
<Button className="mt-0" onClick={this.generatePassword}> <Button className="mt-0" onClick={this.generatePassword}>
<i className="link-operation-icon sf3-font sf3-font-magic"></i> <i className="link-operation-icon sf3-font sf3-font-magic"></i>
</Button> </Button>
</InputGroupAddon>
</InputGroup> </InputGroup>
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Button, Modal, ModalBody, ModalFooter, Input, InputGroupAddon, InputGroup } from 'reactstrap'; import { Button, Modal, ModalBody, ModalFooter, Input, InputGroup, InputGroupText } from 'reactstrap';
import { gettext } from '../../../utils/constants'; import { gettext } from '../../../utils/constants';
import { systemAdminAPI } from '../../../utils/system-admin-api'; import { systemAdminAPI } from '../../../utils/system-admin-api';
import { Utils } from '../../../utils/utils'; import { Utils } from '../../../utils/utils';
@ -66,7 +66,7 @@ class SetGroupQuotaDialog extends React.Component {
onChange={this.handleChange} onChange={this.handleChange}
autoFocus={true} autoFocus={true}
/> />
<InputGroupAddon addonType="append">{'MB'}</InputGroupAddon> <InputGroupText>{'MB'}</InputGroupText>
</InputGroup> </InputGroup>
<p className="tip"> <p className="tip">
<br/><span>{gettext('An integer that is greater than 0 or equal to -2.')}</span><br/> <br/><span>{gettext('An integer that is greater than 0 or equal to -2.')}</span><br/>

View File

@ -1,6 +1,6 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { FormGroup, Label, InputGroup, Input, InputGroupAddon, Button } from 'reactstrap'; import { FormGroup, Label, InputGroup, Input, Button } from 'reactstrap';
import classnames from 'classnames'; import classnames from 'classnames';
import PasswordStrengthChecker from './password-strength-checker'; import PasswordStrengthChecker from './password-strength-checker';
import { isMobile } from '../../../utils/utils'; import { isMobile } from '../../../utils/utils';
@ -53,11 +53,9 @@ const PasswordInput = ({ value, labelValue, enableCheckStrength, onChangeValue }
passwordValue={passwordValue} passwordValue={passwordValue}
/> />
)} )}
<InputGroupAddon addonType="append">
<Button onClick={() => setIsShowPassword(!isShowPassword)}> <Button onClick={() => setIsShowPassword(!isShowPassword)}>
<i className={`password-icon sf3-font sf3-font-eye${isShowPassword ? '' : '-slash'}`} /> <i className={`password-icon sf3-font sf3-font-eye${isShowPassword ? '' : '-slash'}`} />
</Button> </Button>
</InputGroupAddon>
</InputGroup> </InputGroup>
</FormGroup> </FormGroup>
); );

View File

@ -154,6 +154,7 @@ class ItemDropdownMenu extends React.Component {
return ( return (
<Dropdown isOpen={this.state.isItemMenuShow} toggle={this.onDropdownToggleClick}> <Dropdown isOpen={this.state.isItemMenuShow} toggle={this.onDropdownToggleClick}>
<DropdownToggle <DropdownToggle
tag="span"
className={this.props.toggleClass} className={this.props.toggleClass}
data-toggle="dropdown" data-toggle="dropdown"
title={gettext('More operations')} title={gettext('More operations')}
@ -180,7 +181,7 @@ class ItemDropdownMenu extends React.Component {
} }
return ( return (
<Dropdown direction='down' isOpen={this.state.isItemMenuShow} toggle={this.onDropdownToggleClick} className="vam"> <Dropdown tag="span" direction='down' isOpen={this.state.isItemMenuShow} toggle={this.onDropdownToggleClick} className="vam">
<DropdownToggle <DropdownToggle
tag={tagName || 'i'} tag={tagName || 'i'}
role="button" role="button"
@ -199,7 +200,7 @@ class ItemDropdownMenu extends React.Component {
className={this.props.menuClassname} className={this.props.menuClassname}
positionFixed positionFixed
flip={false} flip={false}
modifiers={{ preventOverflow: { boundariesElement: document.body } }} modifiers={[{ name: 'preventOverflow', options: { boundary: document.body } }]}
> >
{menuList.map((menuItem, index) => { {menuList.map((menuItem, index) => {
if (menuItem === 'Divider') { if (menuItem === 'Divider') {
@ -215,7 +216,7 @@ class ItemDropdownMenu extends React.Component {
onMouseMove={(e) => {e.stopPropagation();}} onMouseMove={(e) => {e.stopPropagation();}}
> >
<DropdownToggle <DropdownToggle
tag='div' tag='span'
className="dropdown-item font-weight-normal rounded-0 d-flex align-items-center" className="dropdown-item font-weight-normal rounded-0 d-flex align-items-center"
onMouseEnter={this.toggleSubMenuShown.bind(this, menuItem)} onMouseEnter={this.toggleSubMenuShown.bind(this, menuItem)}
> >
@ -225,7 +226,7 @@ class ItemDropdownMenu extends React.Component {
<DropdownMenu <DropdownMenu
positionFixed positionFixed
flip={false} flip={false}
modifiers={{ preventOverflow: { boundariesElement: document.body } }} modifiers={[{ name: 'preventOverflow', options: { boundary: document.body } }]}
> >
{menuItem.subOpListHeader && <DropdownItem header>{menuItem.subOpListHeader}</DropdownItem>} {menuItem.subOpListHeader && <DropdownItem header>{menuItem.subOpListHeader}</DropdownItem>}
{menuItem.subOpList.map((item, index) => { {menuItem.subOpList.map((item, index) => {

View File

@ -211,11 +211,11 @@ class FileToolbar extends React.Component {
className="file-toolbar-btn" className="file-toolbar-btn"
aria-label={gettext('More operations')} aria-label={gettext('More operations')}
title={gettext('More operations')} title={gettext('More operations')}
tag="div" tag="span"
> >
<Icon symbol="more-vertical" /> <Icon symbol="more-vertical" />
</DropdownToggle> </DropdownToggle>
<DropdownMenu right={true}> <DropdownMenu>
{filePerm == 'rw' && ( {filePerm == 'rw' && (
<a href={`${siteRoot}repo/file_revisions/${repoID}/?p=${encodeURIComponent(filePath)}&referer=${encodeURIComponent(location.href)}`} className="dropdown-item"> <a href={`${siteRoot}repo/file_revisions/${repoID}/?p=${encodeURIComponent(filePath)}&referer=${encodeURIComponent(location.href)}`} className="dropdown-item">
{gettext('History')} {gettext('History')}
@ -249,11 +249,10 @@ class FileToolbar extends React.Component {
</button> </button>
))} ))}
</ButtonGroup> </ButtonGroup>
<DropdownToggle tag="span" className="mx-1" aria-label={gettext('More operations')}>
<DropdownToggle className="mx-1" aria-label={gettext('More operations')}>
<Icon symbol="more-vertical" /> <Icon symbol="more-vertical" />
</DropdownToggle> </DropdownToggle>
<DropdownMenu right={true}> <DropdownMenu>
<DropdownItem> <DropdownItem>
<a href={`${siteRoot}library/${repoID}/${Utils.encodePath(repoName + parentDir)}`} className="text-inherit"> <a href={`${siteRoot}library/${repoID}/${Utils.encodePath(repoName + parentDir)}`} className="text-inherit">
{gettext('Open parent folder')} {gettext('Open parent folder')}

View File

@ -50,14 +50,14 @@ class OnlyofficeFileToolbar extends React.Component {
/> />
<Dropdown isOpen={moreDropdownOpen} toggle={this.toggleMoreOpMenu}> <Dropdown isOpen={moreDropdownOpen} toggle={this.toggleMoreOpMenu}>
<DropdownToggle <DropdownToggle
tag="span"
className="file-toolbar-btn" className="file-toolbar-btn"
aria-label={gettext('More operations')} aria-label={gettext('More operations')}
title={gettext('More operations')} title={gettext('More operations')}
tag="div"
> >
<Icon symbol="more-vertical" /> <Icon symbol="more-vertical" />
</DropdownToggle> </DropdownToggle>
<DropdownMenu right={true}> <DropdownMenu>
<a href={`${siteRoot}library/${repoID}/${Utils.encodePath(repoName + parentDir)}`} className="dropdown-item"> <a href={`${siteRoot}library/${repoID}/${Utils.encodePath(repoName + parentDir)}`} className="dropdown-item">
{gettext('Open parent folder')} {gettext('Open parent folder')}
</a> </a>
@ -72,10 +72,10 @@ class OnlyofficeFileToolbar extends React.Component {
</div> </div>
<Dropdown isOpen={this.state.dropdownOpen} toggle={this.toggle} className="d-block d-md-none flex-shrink-0 ml-4"> <Dropdown isOpen={this.state.dropdownOpen} toggle={this.toggle} className="d-block d-md-none flex-shrink-0 ml-4">
<DropdownToggle className="mx-1" aria-label={gettext('More operations')}> <DropdownToggle tag="span" className="mx-1" aria-label={gettext('More operations')}>
<Icon symbol="more-vertical" /> <Icon symbol="more-vertical" />
</DropdownToggle> </DropdownToggle>
<DropdownMenu right={true}> <DropdownMenu>
<DropdownItem onClick={this.props.toggleHeader}>{gettext('Fold')}</DropdownItem> <DropdownItem onClick={this.props.toggleHeader}>{gettext('Fold')}</DropdownItem>
<DropdownItem onClick={this.props.toggleDetailsPanel}>{gettext('Details')}</DropdownItem> <DropdownItem onClick={this.props.toggleDetailsPanel}>{gettext('Details')}</DropdownItem>
<DropdownItem> <DropdownItem>

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import { createPortal } from 'react-dom';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
const propTypes = { const propTypes = {
@ -23,7 +23,7 @@ class ModalPortal extends React.Component {
} }
render() { render() {
return ReactDOM.createPortal( return createPortal(
this.props.children, this.props.children,
this.el, this.el,
); );

View File

@ -102,6 +102,7 @@ class Paginator extends Component {
<Dropdown isOpen={this.state.isMenuShow} toggle={this.toggleOperationMenu} direction="up" className="paginator-dropdown ml-6"> <Dropdown isOpen={this.state.isMenuShow} toggle={this.toggleOperationMenu} direction="up" className="paginator-dropdown ml-6">
<DropdownToggle <DropdownToggle
tag="span"
data-toggle="dropdown" data-toggle="dropdown"
aria-expanded={this.state.isMenuShow} aria-expanded={this.state.isMenuShow}
onClick={this.toggleOperationMenu} onClick={this.toggleOperationMenu}

View File

@ -1,7 +1,7 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { FormGroup, Label, Input, InputGroup, InputGroupAddon, InputGroupText, FormText } from 'reactstrap'; import { FormGroup, Label, Input, InputGroup, InputGroupText, FormText } from 'reactstrap';
import { gettext } from '../utils/constants'; import { gettext } from '../utils/constants';
import { Utils } from '../utils/utils'; import { Utils } from '../utils/utils';
import DateTimePicker from './date-and-time-picker'; import DateTimePicker from './date-and-time-picker';
@ -85,9 +85,7 @@ class SetLinkExpiration extends React.Component {
<Fragment> <Fragment>
<InputGroup style={{ width: inputWidth }}> <InputGroup style={{ width: inputWidth }}>
<Input type="text" value={expireDays} onChange={onExpireDaysChanged} /> <Input type="text" value={expireDays} onChange={onExpireDaysChanged} />
<InputGroupAddon addonType="append">
<InputGroupText>{gettext('days')}</InputGroupText> <InputGroupText>{gettext('days')}</InputGroupText>
</InputGroupAddon>
</InputGroup> </InputGroup>
{!this.isExpireDaysNoLimit && ( {!this.isExpireDaysNoLimit && (
<FormText color="muted">{this.expirationLimitTip}</FormText> <FormText color="muted">{this.expirationLimitTip}</FormText>

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import { createPortal } from 'react-dom';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
class EditorPortal extends React.Component { class EditorPortal extends React.Component {
@ -32,7 +32,7 @@ class EditorPortal extends React.Component {
return null; return null;
} }
return ReactDOM.createPortal( return createPortal(
this.props.children, this.props.children,
this.el, this.el,
); );

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import { findDOMNode } from 'react-dom';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
class CellMask extends React.PureComponent { class CellMask extends React.PureComponent {
@ -7,7 +7,7 @@ class CellMask extends React.PureComponent {
componentDidUpdate() { componentDidUpdate() {
// Scrolling left and right causes the interface to re-render, // Scrolling left and right causes the interface to re-render,
// and the style of CellMask is reset and needs to be fixed // and the style of CellMask is reset and needs to be fixed
const dom = ReactDOM.findDOMNode(this); const dom = findDOMNode(this);
if (dom.style.position === 'fixed') { if (dom.style.position === 'fixed') {
dom.style.transform = 'none'; dom.style.transform = 'none';
} }

View File

@ -23,7 +23,7 @@ const HeaderDropdownMenu = ({ column, ColumnDropdownMenu, customProps }) => {
<DropdownMenu <DropdownMenu
positionFixed positionFixed
flip={false} flip={false}
modifiers={{ preventOverflow: { boundariesElement: document.body } }} modifiers={[{ name: 'preventOverflow', options: { boundary: document.body } }]}
className="sf-table-dropdown-menu" className="sf-table-dropdown-menu"
> >
{cloneElement(ColumnDropdownMenu, { column, ...customProps })} {cloneElement(ColumnDropdownMenu, { column, ...customProps })}

View File

@ -1,7 +1,7 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { Button, Form, FormGroup, Label, Input, InputGroup, InputGroupAddon, Alert } from 'reactstrap'; import { Button, Form, FormGroup, Label, Input, InputGroup, Alert } from 'reactstrap';
import { gettext, shareLinkExpireDaysMin, shareLinkExpireDaysMax, shareLinkExpireDaysDefault, shareLinkForceUsePassword, shareLinkPasswordMinLength, shareLinkPasswordStrengthLevel, isEmailConfigured } from '../../utils/constants'; import { gettext, shareLinkExpireDaysMin, shareLinkExpireDaysMax, shareLinkExpireDaysDefault, shareLinkForceUsePassword, shareLinkPasswordMinLength, shareLinkPasswordStrengthLevel, isEmailConfigured } from '../../utils/constants';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import { shareLinkAPI } from '../../utils/share-link-api'; import { shareLinkAPI } from '../../utils/share-link-api';
@ -314,14 +314,12 @@ class LinkCreation extends React.Component {
<span className="tip">{gettext('(at least {passwordMinLength} characters and includes {passwordStrengthLevel} of the following: number, upper letter, lower letter and other symbols)').replace('{passwordMinLength}', shareLinkPasswordMinLength).replace('{passwordStrengthLevel}', shareLinkPasswordStrengthLevel)}</span> <span className="tip">{gettext('(at least {passwordMinLength} characters and includes {passwordStrengthLevel} of the following: number, upper letter, lower letter and other symbols)').replace('{passwordMinLength}', shareLinkPasswordMinLength).replace('{passwordStrengthLevel}', shareLinkPasswordStrengthLevel)}</span>
<InputGroup style={{ width: inputWidth }}> <InputGroup style={{ width: inputWidth }}>
<Input id="passwd" type={this.state.isPasswordVisible ? 'text' : 'password'} value={this.state.password || ''} onChange={this.inputPassword} /> <Input id="passwd" type={this.state.isPasswordVisible ? 'text' : 'password'} value={this.state.password || ''} onChange={this.inputPassword} />
<InputGroupAddon addonType="append">
<Button onClick={this.togglePasswordVisible}> <Button onClick={this.togglePasswordVisible}>
<i className={`link-operation-icon sf3-font sf3-font-eye${this.state.isPasswordVisible ? '' : '-slash'}`}></i> <i className={`link-operation-icon sf3-font sf3-font-eye${this.state.isPasswordVisible ? '' : '-slash'}`}></i>
</Button> </Button>
<Button onClick={this.generatePassword}> <Button onClick={this.generatePassword}>
<i className="link-operation-icon sf3-font sf3-font-magic"></i> <i className="link-operation-icon sf3-font sf3-font-magic"></i>
</Button> </Button>
</InputGroupAddon>
</InputGroup> </InputGroup>
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>

View File

@ -2,7 +2,7 @@ import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import copy from 'copy-to-clipboard'; import copy from 'copy-to-clipboard';
import { Button, Input, InputGroup, InputGroupAddon } from 'reactstrap'; import { Button, Input, InputGroup } from 'reactstrap';
import { gettext, shareLinkExpireDaysMin, shareLinkExpireDaysMax, shareLinkExpireDaysDefault, canSendShareLinkEmail } from '../../utils/constants'; import { gettext, shareLinkExpireDaysMin, shareLinkExpireDaysMax, shareLinkExpireDaysDefault, canSendShareLinkEmail } from '../../utils/constants';
import CommonOperationConfirmationDialog from '../../components/dialog/common-operation-confirmation-dialog'; import CommonOperationConfirmationDialog from '../../components/dialog/common-operation-confirmation-dialog';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
@ -198,14 +198,12 @@ class LinkDetails extends React.Component {
<Input type="text" readOnly={true} value={sharedLinkInfo.password} /> : <Input type="text" readOnly={true} value={sharedLinkInfo.password} /> :
<Input type="text" readOnly={true} value={'***************'} /> <Input type="text" readOnly={true} value={'***************'} />
} }
<InputGroupAddon addonType="append">
<Button <Button
aria-label={this.state.storedPasswordVisible ? gettext('Hide') : gettext('Show')} aria-label={this.state.storedPasswordVisible ? gettext('Hide') : gettext('Show')}
onClick={this.toggleStoredPasswordVisible} onClick={this.toggleStoredPasswordVisible}
className={`link-operation-icon eye-icon sf3-font sf3-font-eye${this.state.storedPasswordVisible ? '' : '-slash'}`} className={`link-operation-icon eye-icon sf3-font sf3-font-eye${this.state.storedPasswordVisible ? '' : '-slash'}`}
> >
</Button> </Button>
</InputGroupAddon>
</InputGroup> </InputGroup>
</dd> </dd>
</> </>
@ -235,7 +233,6 @@ class LinkDetails extends React.Component {
) : ( ) : (
<InputGroup className="share-link-details-item"> <InputGroup className="share-link-details-item">
<Input type="text" readOnly={true} value={dayjs(sharedLinkInfo.expire_date).format('YYYY-MM-DD HH:mm:ss')} /> <Input type="text" readOnly={true} value={dayjs(sharedLinkInfo.expire_date).format('YYYY-MM-DD HH:mm:ss')} />
<InputGroupAddon addonType="append">
<Button <Button
aria-label={gettext('Edit')} aria-label={gettext('Edit')}
title={gettext('Edit')} title={gettext('Edit')}
@ -243,7 +240,6 @@ class LinkDetails extends React.Component {
onClick={this.editingExpirationToggle} onClick={this.editingExpirationToggle}
> >
</Button> </Button>
</InputGroupAddon>
</InputGroup> </InputGroup>
)} )}
</dd> </dd>

View File

@ -1,6 +1,6 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Button, Input, InputGroup, InputGroupAddon } from 'reactstrap'; import { Button, Input, InputGroup } from 'reactstrap';
import { gettext } from '../utils/constants'; import { gettext } from '../utils/constants';
import ButtonQR from './btn-qr-code'; import ButtonQR from './btn-qr-code';
@ -20,9 +20,7 @@ class SharedLink extends React.Component {
<div className="d-flex"> <div className="d-flex">
<InputGroup> <InputGroup>
<Input type="text" readOnly={true} value={link} /> <Input type="text" readOnly={true} value={link} />
<InputGroupAddon addonType="append">
<Button color="primary" onClick={copyLink} className="border-0">{gettext('Copy')}</Button> <Button color="primary" onClick={copyLink} className="border-0">{gettext('Copy')}</Button>
</InputGroupAddon>
</InputGroup> </InputGroup>
<ButtonQR link={link} /> <ButtonQR link={link} />
</div> </div>

View File

@ -530,6 +530,7 @@ class SharedRepoListItem extends React.Component {
onMouseMove={(e) => {e.stopPropagation();}} onMouseMove={(e) => {e.stopPropagation();}}
> >
<DropdownToggle <DropdownToggle
tag="span"
className="dropdown-item font-weight-normal rounded-0 d-flex justify-content-between align-items-center pr-2" className="dropdown-item font-weight-normal rounded-0 d-flex justify-content-between align-items-center pr-2"
onMouseEnter={this.toggleAdvancedMenuShown} onMouseEnter={this.toggleAdvancedMenuShown}
> >

View File

@ -47,7 +47,7 @@ class SortMenu extends React.Component {
toggle={this.toggleDropdownMenu} toggle={this.toggleDropdownMenu}
> >
<DropdownToggle <DropdownToggle
tag="div" tag="span"
data-toggle="dropdown" data-toggle="dropdown"
title={gettext('Switch sort mode')} title={gettext('Switch sort mode')}
aria-label={gettext('Switch sort mode')} aria-label={gettext('Switch sort mode')}
@ -58,7 +58,7 @@ class SortMenu extends React.Component {
<i className="sf3-font-down sf3-font"></i> <i className="sf3-font-down sf3-font"></i>
</span> </span>
</DropdownToggle> </DropdownToggle>
<DropdownMenu right={true} className="mt-1"> <DropdownMenu className="mt-1">
{sortOptions.map((item, index) => { {sortOptions.map((item, index) => {
return ( return (
<DropdownItem key={index} onClick={this.props.onSelectSortOption.bind(this, item)} className="pl-5 position-relative"> <DropdownItem key={index} onClick={this.props.onSelectSortOption.bind(this, item)} className="pl-5 position-relative">

View File

@ -1,7 +1,7 @@
import React, { Component, Fragment } from 'react'; import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import toaster from './toast'; import toaster from './toast';
import { Modal, ModalBody, ModalFooter, InputGroup, InputGroupAddon, InputGroupText, Input, Button } from 'reactstrap'; import { Modal, ModalBody, ModalFooter, InputGroup, InputGroupText, Input, Button } from 'reactstrap';
import { gettext, serviceURL } from '../utils/constants'; import { gettext, serviceURL } from '../utils/constants';
import { Utils } from '../utils/utils'; import { Utils } from '../utils/utils';
import { subscriptionAPI } from '../utils/subscription-api'; import { subscriptionAPI } from '../utils/subscription-api';
@ -184,9 +184,7 @@ class Plans extends Component {
{'¥ '}<span className="price-version-plan-price">{currentPlan.price}</span>{' ' + currentPlan.description} {'¥ '}<span className="price-version-plan-price">{currentPlan.price}</span>{' ' + currentPlan.description}
</span> </span>
<InputGroup style={{ marginBottom: '5px' }} className='user-numbers'> <InputGroup style={{ marginBottom: '5px' }} className='user-numbers'>
<InputGroupAddon addonType="prepend">
<InputGroupText>{operationIntro}</InputGroupText> <InputGroupText>{operationIntro}</InputGroupText>
</InputGroupAddon>
<Input <Input
className="py-2" className="py-2"
placeholder={operationIntro} placeholder={operationIntro}
@ -225,9 +223,7 @@ class Plans extends Component {
{'¥ '}<span className="price-version-plan-price">{currentPlan.asset_quota_price}</span>{' ' + currentPlan.asset_quota_description} {'¥ '}<span className="price-version-plan-price">{currentPlan.asset_quota_price}</span>{' ' + currentPlan.asset_quota_description}
</span> </span>
<InputGroup style={{ marginBottom: '5px' }} className='space-quota'> <InputGroup style={{ marginBottom: '5px' }} className='space-quota'>
<InputGroupAddon addonType="prepend">
<InputGroupText><span className="font-500">{operationIntro}</span></InputGroupText> <InputGroupText><span className="font-500">{operationIntro}</span></InputGroupText>
</InputGroupAddon>
<Input <Input
className="py-2" className="py-2"
placeholder={operationIntro} placeholder={operationIntro}
@ -239,9 +235,7 @@ class Plans extends Component {
disabled={!currentPlan.can_custom_asset_quota} disabled={!currentPlan.can_custom_asset_quota}
onChange={this.onAssetQuotaUnitCountInputChange} onChange={this.onAssetQuotaUnitCountInputChange}
/> />
<InputGroupAddon addonType='append'>
<InputGroupText><span className="font-500">{' x ' + currentPlan.asset_quota_unit + 'GB'}</span></InputGroupText> <InputGroupText><span className="font-500">{' x ' + currentPlan.asset_quota_unit + 'GB'}</span></InputGroupText>
</InputGroupAddon>
</InputGroup> </InputGroup>
<span className='py-4 text-orange mb-0 font-500 price-version-plan-whole-price text-center'> <span className='py-4 text-orange mb-0 font-500 price-version-plan-whole-price text-center'>
{'总价 ¥ ' + totalAmount} {'总价 ¥ ' + totalAmount}

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import { createRoot } from 'react-dom/client';
import ToastManager from './toastManager'; import ToastManager from './toastManager';
import './toaster.css'; import './toaster.css';
@ -18,14 +18,15 @@ export default class Toaster {
container.setAttribute('data-evergreen-toaster-container', ''); container.setAttribute('data-evergreen-toaster-container', '');
document.body.appendChild(container); document.body.appendChild(container);
ReactDOM.render( const root = createRoot(container);
root.render(
<ToastManager <ToastManager
bindNotify={this._bindNotify} bindNotify={this._bindNotify}
bindGetToasts={this._bindGetToasts} bindGetToasts={this._bindGetToasts}
bindCloseAll={this._bindCloseAll} bindCloseAll={this._bindCloseAll}
/>, />
container
); );
} }
_bindNotify = handler => { _bindNotify = handler => {

View File

@ -285,7 +285,7 @@ class DirOperationToolbar extends React.Component {
<Fragment> <Fragment>
<Dropdown isOpen={this.state.isDesktopMenuOpen} toggle={this.toggleDesktopOpMenu}> <Dropdown isOpen={this.state.isDesktopMenuOpen} toggle={this.toggleDesktopOpMenu}>
<DropdownToggle <DropdownToggle
tag="div" tag="span"
role="button" role="button"
className="path-item" className="path-item"
onClick={this.toggleDesktopOpMenu} onClick={this.toggleDesktopOpMenu}
@ -310,7 +310,7 @@ class DirOperationToolbar extends React.Component {
onMouseMove={(e) => {e.stopPropagation();}} onMouseMove={(e) => {e.stopPropagation();}}
> >
<DropdownToggle <DropdownToggle
tag='div' tag='span'
className="dropdown-item font-weight-normal rounded-0 d-flex align-items-center" className="dropdown-item font-weight-normal rounded-0 d-flex align-items-center"
onMouseEnter={this.toggleSubMenuShown.bind(this, item)} onMouseEnter={this.toggleSubMenuShown.bind(this, item)}
> >
@ -346,7 +346,7 @@ class DirOperationToolbar extends React.Component {
content = ( content = (
<Dropdown isOpen={this.state.isMobileOpMenuOpen} toggle={this.toggleMobileOpMenu}> <Dropdown isOpen={this.state.isMobileOpMenuOpen} toggle={this.toggleMobileOpMenu}>
<DropdownToggle <DropdownToggle
tag="div" tag="span"
role="button" role="button"
className="path-item" className="path-item"
> >

View File

@ -149,7 +149,7 @@ class ViewFileToolbar extends React.Component {
{opList.length > 0 && {opList.length > 0 &&
<Dropdown isOpen={this.state.isDropdownMenuOpen} toggle={this.toggleDropdownMenu} className="view-file-toolbar-dropdown"> <Dropdown isOpen={this.state.isDropdownMenuOpen} toggle={this.toggleDropdownMenu} className="view-file-toolbar-dropdown">
<DropdownToggle <DropdownToggle
tag="div" tag="span"
role="button" role="button"
className="path-item" className="path-item"
onClick={this.toggleDropdownMenu} onClick={this.toggleDropdownMenu}
@ -174,6 +174,7 @@ class ViewFileToolbar extends React.Component {
onMouseMove={(e) => {e.stopPropagation();}} onMouseMove={(e) => {e.stopPropagation();}}
> >
<DropdownToggle <DropdownToggle
tag="span"
className="dropdown-item font-weight-normal rounded-0 d-flex align-items-center" className="dropdown-item font-weight-normal rounded-0 d-flex align-items-center"
onMouseEnter={this.toggleSubMenuShown.bind(this, item)} onMouseEnter={this.toggleSubMenuShown.bind(this, item)}
> >

View File

@ -60,7 +60,7 @@ class ViewModes extends React.Component {
id="cur-view-change-mode-dropdown" id="cur-view-change-mode-dropdown"
> >
<DropdownToggle <DropdownToggle
tag="div" tag="span"
data-toggle="dropdown" data-toggle="dropdown"
title={gettext('Switch view mode')} title={gettext('Switch view mode')}
aria-label={gettext('Switch view mode')} aria-label={gettext('Switch view mode')}
@ -71,7 +71,7 @@ class ViewModes extends React.Component {
<span className={'sf3-font sf3-font-down'}></span> <span className={'sf3-font sf3-font-down'}></span>
</span> </span>
</DropdownToggle> </DropdownToggle>
<DropdownMenu right={true} className="mt-1"> <DropdownMenu className="mt-1">
{options.map((item, index) => { {options.map((item, index) => {
return ( return (
<DropdownItem className='p-0' key={index} onClick={this.props.switchViewMode.bind(this, item.value)}> <DropdownItem className='p-0' key={index} onClick={this.props.switchViewMode.bind(this, item.value)}>

View File

@ -235,7 +235,7 @@ class WikiCardItem extends Component {
aria-haspopup={true} aria-haspopup={true}
style={{ 'minWidth': '0' }} style={{ 'minWidth': '0' }}
/> />
<DropdownMenu right={true} className="dtable-dropdown-menu"> <DropdownMenu className="dtable-dropdown-menu">
{showRename && {showRename &&
<DropdownItem onClick={this.onRenameToggle}>{gettext('Rename')}</DropdownItem>} <DropdownItem onClick={this.onRenameToggle}>{gettext('Rename')}</DropdownItem>}
{showPublish && canPublishWiki && {showPublish && canPublishWiki &&

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import './css/draft.css'; import './css/draft.css';
@ -12,4 +12,5 @@ export default function Draft() {
); );
} }
ReactDom.render(<Draft />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<Draft />);

View File

@ -1,5 +1,5 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import { Button } from 'reactstrap'; import { Button } from 'reactstrap';
import { Utils } from './utils/utils'; import { Utils } from './utils/utils';
import { seafileAPI } from './utils/seafile-api'; import { seafileAPI } from './utils/seafile-api';
@ -275,4 +275,5 @@ class FileHistory extends React.Component {
} }
} }
ReactDom.render(<FileHistory />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<FileHistory />,);

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import axios from 'axios'; import axios from 'axios';
import { fileName, historyRepoID } from './utils/constants'; import { fileName, historyRepoID } from './utils/constants';
import SidePanel from './pages/file-history/side-panel'; import SidePanel from './pages/file-history/side-panel';
@ -69,4 +69,5 @@ class FileHistory extends React.Component {
} }
} }
ReactDom.render(<FileHistory />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<FileHistory />);

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import FileView from './components/file-view/file-view'; import FileView from './components/file-view/file-view';
import FileViewTip from './components/file-view/file-view-tip'; import FileViewTip from './components/file-view/file-view-tip';
import Image from './components/file-content-view/image'; import Image from './components/file-content-view/image';
@ -88,4 +88,5 @@ class InnerFileView extends React.Component {
} }
} }
ReactDom.render(<InnerFileView />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<InnerFileView />);

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import FileView from './components/history-trash-file-view/file-view'; import FileView from './components/history-trash-file-view/file-view';
import FileViewTip from './components/history-trash-file-view/file-view-tip'; import FileViewTip from './components/history-trash-file-view/file-view-tip';
import Image from './components/file-content-view/image'; import Image from './components/file-content-view/image';
@ -60,4 +60,5 @@ class HistoryTrashFileView extends React.Component {
} }
} }
ReactDom.render(<HistoryTrashFileView />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<HistoryTrashFileView />);

View File

@ -1,6 +1,6 @@
// Import React! // Import React!
import React, { Suspense } from 'react'; import React, { Suspense } from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import { I18nextProvider } from 'react-i18next'; import { I18nextProvider } from 'react-i18next';
import i18n from './_i18n/i18n-seafile-editor'; import i18n from './_i18n/i18n-seafile-editor';
import MarkdownEditor from './pages/markdown-editor'; import MarkdownEditor from './pages/markdown-editor';
@ -12,7 +12,8 @@ import './index.css';
const { repoID, repoEncrypted, filePerm } = window.app.pageOptions; const { repoID, repoEncrypted, filePerm } = window.app.pageOptions;
ReactDom.render( const root = createRoot(document.getElementById('root'));
root.render(
<I18nextProvider i18n={ i18n } > <I18nextProvider i18n={ i18n } >
<Suspense fallback={<Loading />}> <Suspense fallback={<Loading />}>
<MetadataStatusProvider repoID={repoID} repoInfo={{ permission: filePerm, encrypted: repoEncrypted }}> <MetadataStatusProvider repoID={repoID} repoInfo={{ permission: filePerm, encrypted: repoEncrypted }}>
@ -21,6 +22,5 @@ ReactDom.render(
</CollaboratorsProvider> </CollaboratorsProvider>
</MetadataStatusProvider> </MetadataStatusProvider>
</Suspense> </Suspense>
</I18nextProvider>, </I18nextProvider>
document.getElementById('root')
); );

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import { createPortal } from 'react-dom';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
class EditorPortal extends React.Component { class EditorPortal extends React.Component {
@ -32,7 +32,7 @@ class EditorPortal extends React.Component {
return null; return null;
} }
return ReactDOM.createPortal( return createPortal(
this.props.children, this.props.children,
this.el, this.el,
); );

View File

@ -1,5 +1,4 @@
import React, { forwardRef, useMemo, useImperativeHandle, useCallback, useState, useRef, useEffect } from 'react'; import React, { forwardRef, useMemo, useImperativeHandle, useCallback, useState, useRef, useEffect } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Utils } from '../../../utils/utils'; import { Utils } from '../../../utils/utils';
import { getNumberDisplayString, replaceNumberNotAllowInput, formatStringToNumber } from '../../utils/cell'; import { getNumberDisplayString, replaceNumberNotAllowInput, formatStringToNumber } from '../../utils/cell';
@ -72,7 +71,7 @@ const NumberEditor = forwardRef(({
return { [key]: formatStringToNumber(value, data) }; return { [key]: formatStringToNumber(value, data) };
}, },
getInputNode: () => { getInputNode: () => {
const domNode = ReactDOM.findDOMNode(inputRef.current); const domNode = inputRef.current;
if (domNode.tagName === 'INPUT') return domNode; if (domNode.tagName === 'INPUT') return domNode;
return domNode.querySelector('input:not([type=hidden])'); return domNode.querySelector('input:not([type=hidden])');
}, },

View File

@ -54,7 +54,7 @@ const RateItem = ({
<Icon iconName={type || 'rate'} /> <Icon iconName={type || 'rate'} />
</div> </div>
{enterIndex !== -1 && ( {enterIndex !== -1 && (
<UncontrolledTooltip placement='bottom' target={ref} modifiers={{ preventOverflow: { boundariesElement: document.body } }} className="sf-metadata-tooltip"> <UncontrolledTooltip placement='bottom' target={ref} modifiers={[{ name: 'preventOverflow', options: { boundary: document.body } }]} className="sf-metadata-tooltip">
{enterIndex} {enterIndex}
</UncontrolledTooltip> </UncontrolledTooltip>
)} )}

View File

@ -1,6 +1,6 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import ReactDOM from 'react-dom'; import { findDOMNode } from 'react-dom';
import classnames from 'classnames'; import classnames from 'classnames';
import { KeyCodes } from '../../../../constants'; import { KeyCodes } from '../../../../constants';
import { CellValueType } from './constants'; import { CellValueType } from './constants';
@ -105,7 +105,7 @@ class SimpleTextEditor extends Component {
}; };
getInputNode = () => { getInputNode = () => {
const domNode = ReactDOM.findDOMNode(this.input); const domNode = findDOMNode(this.input);
if (domNode.tagName === 'INPUT') { if (domNode.tagName === 'INPUT') {
return domNode; return domNode;
} }
@ -118,11 +118,6 @@ class SimpleTextEditor extends Component {
return this.input; return this.input;
}; };
onSaveQRCodeValue = (value) => {
this.setState({ value });
this.props.onCommit();
};
render() { render() {
const { column, readOnly, className, placeholder } = this.props; const { column, readOnly, className, placeholder } = this.props;
const { value } = this.state; const { value } = this.state;

View File

@ -157,7 +157,7 @@ const AI = () => {
{isMenuShow && ( {isMenuShow && (
<ModalPortal> <ModalPortal>
<div className="sf-metadata-ai-dropdown-menu large"> <div className="sf-metadata-ai-dropdown-menu large">
<DropdownMenu right={true}> <DropdownMenu>
{options.map(op => (<DropdownItem key={op.value} onClick={() => handelOperation(op)}>{op.label}</DropdownItem>))} {options.map(op => (<DropdownItem key={op.value} onClick={() => handelOperation(op)}>{op.label}</DropdownItem>))}
</DropdownMenu> </DropdownMenu>
</div> </div>

View File

@ -65,7 +65,7 @@ const RateData = ({ value, onChange, updatePopoverState }) => {
className="sf-metadata-rate-column-data-style-setting-popover" className="sf-metadata-rate-column-data-style-setting-popover"
hide={closeStylePopover} hide={closeStylePopover}
hideWithEsc={closeStylePopover} hideWithEsc={closeStylePopover}
modifiers={{ preventOverflow: { boundariesElement: document.body } }} modifiers={[{ name: 'preventOverflow', options: { boundary: document.body } }]}
> >
<div className="rate-column-style-list"> <div className="rate-column-style-list">
{RATE_COLORS.map(color => { {RATE_COLORS.map(color => {

View File

@ -48,7 +48,7 @@ const KanbanAddCategoryPopover = ({ target, options, onCancel, onSubmit }) => {
className="sf-metadata-kanban-add-board-popover" className="sf-metadata-kanban-add-board-popover"
hide={onCancel} hide={onCancel}
hideWithEsc={onCancel} hideWithEsc={onCancel}
modifiers={{ preventOverflow: { boundariesElement: document.body } }} modifiers={[[{ name: 'preventOverflow', options: { boundary: document.body } }]]}
> >
<div className="sf-metadata-kanban-add-board-popover-inner"> <div className="sf-metadata-kanban-add-board-popover-inner">
<div className="kanban-popover-body"> <div className="kanban-popover-body">

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import { findDOMNode } from 'react-dom';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
class CellMask extends React.PureComponent { class CellMask extends React.PureComponent {
@ -7,7 +7,7 @@ class CellMask extends React.PureComponent {
componentDidUpdate() { componentDidUpdate() {
// Scrolling left and right causes the interface to re-render, // Scrolling left and right causes the interface to re-render,
// and the style of CellMask is reset and needs to be fixed // and the style of CellMask is reset and needs to be fixed
const dom = ReactDOM.findDOMNode(this); const dom = findDOMNode(this);
if (dom.style.position === 'fixed') { if (dom.style.position === 'fixed') {
dom.style.transform = 'none'; dom.style.transform = 'none';
} }

View File

@ -0,0 +1,55 @@
import React, { useMemo } from 'react';
import PropTypes from 'prop-types';
import { UncontrolledTooltip } from 'reactstrap';
import { IconBtn } from '@seafile/sf-metadata-ui-component';
import { gettext } from '../../../../../../../../../utils/constants';
import { EVENT_BUS_TYPE as METADATA_EVENT_BUS_TYPE, EDITOR_TYPE } from '../../../../../../../../constants';
import { checkIsDir } from '../../../../../../../../utils/row';
import { openFile } from '../../../../../../../../utils/file';
import './index.css';
const FileNameOperationBtn = ({ column, record, ...props }) => {
const fileName = useMemo(() => {
const { key } = column;
return record[key];
}, [column, record]);
const isDir = useMemo(() => checkIsDir(record), [record]);
const handelClick = (event) => {
event.stopPropagation();
event.nativeEvent.stopImmediatePropagation();
const repoID = window.sfMetadataContext.getSetting('repoID');
openFile(repoID, record, () => {
window.sfMetadataContext.eventBus.dispatch(METADATA_EVENT_BUS_TYPE.OPEN_EDITOR, EDITOR_TYPE.PREVIEWER);
});
};
if (!fileName) return null;
return (
<>
<IconBtn id="sf-metadata-cell-open-file-btn" className="sf-metadata-cell-operation-btn" size={20} iconName="open-file" onClick={handelClick} />
<UncontrolledTooltip
hideArrow
target="sf-metadata-cell-open-file-btn"
placement="bottom"
fade={false}
delay={{ show: 0, hide: 0 }}
modifiers={[{ name: 'preventOverflow', options: { boundary: document.body } }]}
className="sf-metadata-tooltip"
>
{isDir ? gettext('Open folder') : gettext('Open file')}
</UncontrolledTooltip>
</>
);
};
FileNameOperationBtn.propTypes = {
column: PropTypes.object,
record: PropTypes.object,
};
export default FileNameOperationBtn;

View File

@ -122,7 +122,7 @@ class MoreMenu extends React.PureComponent {
aria-expanded={this.state.dropdownOpen} aria-expanded={this.state.dropdownOpen}
> >
</DropdownToggle> </DropdownToggle>
<DropdownMenu className="drop-list" right={true}> <DropdownMenu className="drop-list">
{index !== 0 && <a href="#" onClick={onItemRestore}><DropdownItem>{gettext('Restore')}</DropdownItem></a>} {index !== 0 && <a href="#" onClick={onItemRestore}><DropdownItem>{gettext('Restore')}</DropdownItem></a>}
{canDownload && <a href={downloadUrl}><DropdownItem>{gettext('Download')}</DropdownItem></a>} {canDownload && <a href={downloadUrl}><DropdownItem>{gettext('Download')}</DropdownItem></a>}
<a href={viewUrl}><DropdownItem>{gettext('View')}</DropdownItem></a> <a href={viewUrl}><DropdownItem>{gettext('View')}</DropdownItem></a>

View File

@ -1,5 +1,5 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import MediaQuery from 'react-responsive'; import MediaQuery from 'react-responsive';
import { Modal } from 'reactstrap'; import { Modal } from 'reactstrap';
import SidePanel from './side-panel'; import SidePanel from './side-panel';
@ -29,4 +29,5 @@ export default function Institutions() {
); );
} }
ReactDom.render(<Institutions />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<Institutions />);

View File

@ -18,7 +18,7 @@ class CollabUsersButton extends React.PureComponent {
render() { render() {
return ( return (
<Dropdown className={this.props.className} isOpen={this.state.dropdownOpen} toggle={this.dropdownToggle}> <Dropdown className={this.props.className} isOpen={this.state.dropdownOpen} toggle={this.dropdownToggle}>
<DropdownToggle id={this.props.id}> <DropdownToggle tag="span" id={this.props.id}>
<i className="iconfont icon-users"></i> {this.props.users.length} <i className="iconfont icon-users"></i> {this.props.users.length}
</DropdownToggle> </DropdownToggle>
<DropdownMenu className={'drop-list'}> <DropdownMenu className={'drop-list'}>

View File

@ -51,12 +51,12 @@ class MoreMenu extends React.PureComponent {
const isSmall = this.props.isSmallScreen; const isSmall = this.props.isSmallScreen;
return ( return (
<Dropdown isOpen={this.state.dropdownOpen} toggle={this.dropdownToggle} direction="down"> <Dropdown isOpen={this.state.dropdownOpen} toggle={this.dropdownToggle} direction="down">
<DropdownToggle id="moreButton" aria-label={gettext('More operations')}> <DropdownToggle tag="span" id="moreButton" aria-label={gettext('More operations')}>
<Icon symbol="more-vertical" /> <Icon symbol="more-vertical" />
<Tooltip toggle={this.tooltipToggle} delay={{ show: 0, hide: 0 }} target="moreButton" placement='bottom' isOpen={this.state.tooltipOpen}>{gettext('More')} <Tooltip toggle={this.tooltipToggle} delay={{ show: 0, hide: 0 }} target="moreButton" placement='bottom' isOpen={this.state.tooltipOpen}>{gettext('More')}
</Tooltip> </Tooltip>
</DropdownToggle> </DropdownToggle>
<DropdownMenu className="drop-list" right={true}> <DropdownMenu className="drop-list">
{(!this.props.readOnly && editorMode === 'rich') && {(!this.props.readOnly && editorMode === 'rich') &&
<DropdownItem onClick={this.props.onEdit.bind(this, 'plain')}>{gettext('Switch to plain text editor')}</DropdownItem>} <DropdownItem onClick={this.props.onEdit.bind(this, 'plain')}>{gettext('Switch to plain text editor')}</DropdownItem>}
{(!this.props.readOnly && editorMode === 'plain') && {(!this.props.readOnly && editorMode === 'plain') &&

View File

@ -221,6 +221,7 @@ class MylibRepoMenu extends React.Component {
onMouseMove={(e) => {e.stopPropagation();}} onMouseMove={(e) => {e.stopPropagation();}}
> >
<DropdownToggle <DropdownToggle
tag="span"
className="dropdown-item font-weight-normal rounded-0 d-flex justify-content-between align-items-center pr-2" className="dropdown-item font-weight-normal rounded-0 d-flex justify-content-between align-items-center pr-2"
onMouseEnter={this.toggleAdvancedMenuShown} onMouseEnter={this.toggleAdvancedMenuShown}
> >

View File

@ -6,7 +6,7 @@ import { gettext } from '../../../utils/constants';
function DepartmentNodeMenu({ node, toggleDelete, toggleRename, toggleAddMembers, toggleAddDepartment, toggleAddLibrary }) { function DepartmentNodeMenu({ node, toggleDelete, toggleRename, toggleAddMembers, toggleAddDepartment, toggleAddLibrary }) {
return ( return (
<DropdownMenu <DropdownMenu
modifiers={{ preventOverflow: { boundariesElement: document.body } }} modifiers={[{ name: 'preventOverflow', options: { boundary: document.body } }]}
positionFixed={true} positionFixed={true}
> >
<DropdownItem key={`${node.id}-add-department`} onClick={() => toggleAddDepartment(node)}> <DropdownItem key={`${node.id}-add-department`} onClick={() => toggleAddDepartment(node)}>

View File

@ -118,7 +118,7 @@ class DepartmentsV2MembersItem extends React.Component {
aria-label={gettext('More operations')} aria-label={gettext('More operations')}
data-toggle="dropdown" data-toggle="dropdown"
/> />
<DropdownMenu right={true}> <DropdownMenu>
<DropdownItem key='delete' onClick={this.toggleDeleteMemberDialog}>{gettext('Delete')}</DropdownItem> <DropdownItem key='delete' onClick={this.toggleDeleteMemberDialog}>{gettext('Delete')}</DropdownItem>
</DropdownMenu> </DropdownMenu>
</Dropdown> </Dropdown>

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import { Router } from '@gatsbyjs/reach-router'; import { Router } from '@gatsbyjs/reach-router';
import { siteRoot, enableMultiADFS } from '../../utils/constants'; import { siteRoot, enableMultiADFS } from '../../utils/constants';
import SidePanel from './side-panel'; import SidePanel from './side-panel';
@ -135,4 +135,5 @@ class Org extends React.Component {
} }
} }
ReactDom.render(<Org />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<Org />);

View File

@ -1,5 +1,5 @@
import React, { Component, Fragment } from 'react'; import React, { Component, Fragment } from 'react';
import { Input, InputGroup, InputGroupAddon, Button, Row, Col, Label } from 'reactstrap'; import { Input, InputGroup, Button, Row, Col, Label } from 'reactstrap';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { gettext } from '../../utils/constants'; import { gettext } from '../../utils/constants';
@ -67,11 +67,9 @@ class OrgSamlConfigInput extends Component {
<Col md="5"> <Col md="5">
<InputGroup> <InputGroup>
<Input type={inputType} value={value} onChange={this.onInputChange} onFocus={this.toggleBtns} onBlur={this.hideBtns}/> <Input type={inputType} value={value} onChange={this.onInputChange} onFocus={this.toggleBtns} onBlur={this.hideBtns}/>
{this.props.domainVerified && {this.props.domainVerified && (
<InputGroupAddon addonType="append">
<Button color="success" className="border-0">{gettext('Verified')}</Button> <Button color="success" className="border-0">{gettext('Verified')}</Button>
</InputGroupAddon> )}
}
</InputGroup> </InputGroup>
{this.props.isCertificate && {this.props.isCertificate &&
<p className="small text-secondary mt-1"> <p className="small text-secondary mt-1">

View File

@ -1,5 +1,5 @@
import React, { Fragment, Component } from 'react'; import React, { Fragment, Component } from 'react';
import { Row, Col, Label, Button, Input, InputGroup, InputGroupAddon } from 'reactstrap'; import { Row, Col, Label, Button, Input, InputGroup } from 'reactstrap';
import copy from 'copy-to-clipboard'; import copy from 'copy-to-clipboard';
import MainPanelTopbar from './main-panel-topbar'; import MainPanelTopbar from './main-panel-topbar';
import toaster from '../../components/toast'; import toaster from '../../components/toast';
@ -114,9 +114,7 @@ class OrgSAMLConfig extends Component {
<Col md="5"> <Col md="5">
<InputGroup> <InputGroup>
<Input type="text" readOnly={true} value={entityID} /> <Input type="text" readOnly={true} value={entityID} />
<InputGroupAddon addonType="append">
<Button color="primary" onClick={this.onCopyValue.bind(this, entityID)} className="border-0">{gettext('Copy')}</Button> <Button color="primary" onClick={this.onCopyValue.bind(this, entityID)} className="border-0">{gettext('Copy')}</Button>
</InputGroupAddon>
</InputGroup> </InputGroup>
</Col> </Col>
</Row> </Row>
@ -128,9 +126,7 @@ class OrgSAMLConfig extends Component {
<Col md="5"> <Col md="5">
<InputGroup> <InputGroup>
<Input type="text" readOnly={true} value={acsURL} /> <Input type="text" readOnly={true} value={acsURL} />
<InputGroupAddon addonType="append">
<Button color="primary" onClick={this.onCopyValue.bind(this, acsURL)} className="border-0">{gettext('Copy')}</Button> <Button color="primary" onClick={this.onCopyValue.bind(this, acsURL)} className="border-0">{gettext('Copy')}</Button>
</InputGroupAddon>
</InputGroup> </InputGroup>
</Col> </Col>
</Row> </Row>
@ -142,9 +138,7 @@ class OrgSAMLConfig extends Component {
<Col md="5"> <Col md="5">
<InputGroup> <InputGroup>
<Input type="text" readOnly={true} value={serviceURL} /> <Input type="text" readOnly={true} value={serviceURL} />
<InputGroupAddon addonType="append">
<Button color="primary" onClick={this.onCopyValue.bind(this, serviceURL)} className="border-0">{gettext('Copy')}</Button> <Button color="primary" onClick={this.onCopyValue.bind(this, serviceURL)} className="border-0">{gettext('Copy')}</Button>
</InputGroupAddon>
</InputGroup> </InputGroup>
</Col> </Col>
</Row> </Row>
@ -156,9 +150,7 @@ class OrgSAMLConfig extends Component {
<Col md="5"> <Col md="5">
<InputGroup> <InputGroup>
<Input type="text" readOnly={true} value={logoutURL} /> <Input type="text" readOnly={true} value={logoutURL} />
<InputGroupAddon addonType="append">
<Button color="primary" onClick={this.onCopyValue.bind(this, logoutURL)} className="border-0">{gettext('Copy')}</Button> <Button color="primary" onClick={this.onCopyValue.bind(this, logoutURL)} className="border-0">{gettext('Copy')}</Button>
</InputGroupAddon>
</InputGroup> </InputGroup>
</Col> </Col>
</Row> </Row>
@ -204,9 +196,7 @@ class OrgSAMLConfig extends Component {
<InputGroup> <InputGroup>
<Input type="text" readOnly={true} value={dnsTxt}/> <Input type="text" readOnly={true} value={dnsTxt}/>
{(dnsTxt && !domainVerified) && {(dnsTxt && !domainVerified) &&
<InputGroupAddon addonType="append">
<Button color="primary" onClick={this.onCopyValue.bind(this, dnsTxt)} className="border-0">{gettext('Copy')}</Button> <Button color="primary" onClick={this.onCopyValue.bind(this, dnsTxt)} className="border-0">{gettext('Copy')}</Button>
</InputGroupAddon>
} }
</InputGroup> </InputGroup>
{(dnsTxt && !domainVerified) && {(dnsTxt && !domainVerified) &&

View File

@ -8,7 +8,7 @@ import MainPanelTopbar from '../main-panel-topbar';
import Section from './section'; import Section from './section';
import InputItem from './input-item'; import InputItem from './input-item';
import FileItem from './file-item'; import FileItem from './file-item';
import { InputGroupAddon, InputGroupText } from 'reactstrap'; import { InputGroupText } from 'reactstrap';
import '../../../css/system-admin-web-settings.css'; import '../../../css/system-admin-web-settings.css';
import CheckboxItem from '../../sys-admin/web-settings/checkbox-item'; import CheckboxItem from '../../sys-admin/web-settings/checkbox-item';
@ -192,9 +192,7 @@ class OrgWebSettings extends Component {
value={user_default_quota} value={user_default_quota}
helpTip={gettext('Tip: 0 means default limit, the unit is MB')} helpTip={gettext('Tip: 0 means default limit, the unit is MB')}
inputAddon={ inputAddon={
<InputGroupAddon addonType="append">
<InputGroupText>MB</InputGroupText> <InputGroupText>MB</InputGroupText>
</InputGroupAddon>
} }
valueFixed={1} valueFixed={1}
/> />

View File

@ -1,5 +1,5 @@
import React, { useState, useRef, useCallback, useLayoutEffect, useEffect } from 'react'; import React, { useState, useRef, useCallback, useLayoutEffect, useEffect } from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import isHotkey from 'is-hotkey'; import isHotkey from 'is-hotkey';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { processor } from '@seafile/seafile-editor'; import { processor } from '@seafile/seafile-editor';
@ -262,4 +262,5 @@ PlainMarkdownEditor.propTypes = propTypes;
export default PlainMarkdownEditor; export default PlainMarkdownEditor;
ReactDom.render(<PlainMarkdownEditor />, document.getElementById('root')); const root = createRoot(document.getElementById('wrapper'));
root.render(<PlainMarkdownEditor />);

View File

@ -171,7 +171,7 @@ class SidePanel extends Component {
aria-expanded={this.state.isHeaderMenuShow} aria-expanded={this.state.isHeaderMenuShow}
onClick={this.onDropdownToggleClick} onClick={this.onDropdownToggleClick}
/> />
<DropdownMenu right> <DropdownMenu>
<DropdownItem onClick={this.onAddFolderToggle.bind(this, 'root')}>{gettext('New Folder')}</DropdownItem> <DropdownItem onClick={this.onAddFolderToggle.bind(this, 'root')}>{gettext('New Folder')}</DropdownItem>
<DropdownItem onClick={this.onAddFileToggle.bind(this, 'root')}>{gettext('New File')}</DropdownItem> <DropdownItem onClick={this.onAddFileToggle.bind(this, 'root')}>{gettext('New File')}</DropdownItem>
</DropdownMenu> </DropdownMenu>

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import { Button } from 'reactstrap'; import { Button } from 'reactstrap';
import { DiffViewer } from '@seafile/sdoc-editor'; import { DiffViewer } from '@seafile/sdoc-editor';
import { gettext } from '../../utils/constants'; import { gettext } from '../../utils/constants';
@ -133,4 +133,5 @@ class SdocRevision extends React.Component {
} }
} }
ReactDom.render(<SdocRevision />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<SdocRevision />);

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import { I18nextProvider } from 'react-i18next'; import { I18nextProvider } from 'react-i18next';
import i18n from '../../../_i18n/i18n-sdoc-editor'; import i18n from '../../../_i18n/i18n-sdoc-editor';
import { UncontrolledTooltip } from 'reactstrap'; import { UncontrolledTooltip } from 'reactstrap';
@ -436,8 +436,9 @@ class SdocFileHistory extends React.Component {
} }
} }
ReactDom.render( const root = createRoot(document.getElementById('wrapper'));
root.render(
<I18nextProvider i18n={ i18n } > <I18nextProvider i18n={ i18n } >
<SdocFileHistory /> <SdocFileHistory />
</I18nextProvider>, </I18nextProvider>
document.getElementById('wrapper')); );

View File

@ -1,5 +1,5 @@
import React, { Suspense } from 'react'; import React, { Suspense } from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import { I18nextProvider } from 'react-i18next'; import { I18nextProvider } from 'react-i18next';
import { PublishedRevisionViewer } from '@seafile/sdoc-editor'; import { PublishedRevisionViewer } from '@seafile/sdoc-editor';
import i18n from '../../../_i18n/i18n-sdoc-editor'; import i18n from '../../../_i18n/i18n-sdoc-editor';
@ -45,11 +45,11 @@ window.seafile = {
revisionId, revisionId,
}; };
ReactDom.render( const root = createRoot(document.getElementById('wrapper'));
root.render(
<I18nextProvider i18n={ i18n } > <I18nextProvider i18n={ i18n } >
<Suspense fallback={<Loading />}> <Suspense fallback={<Loading />}>
<PublishedRevisionViewer /> <PublishedRevisionViewer />
</Suspense> </Suspense>
</I18nextProvider>, </I18nextProvider>
document.getElementById('wrapper')
); );

View File

@ -6,7 +6,7 @@ import { gettext } from '../../../utils/constants';
function DepartmentNodeMenu({ node, toggleDelete, toggleRename, toggleAddMembers, toggleAddDepartment, toggleAddLibrary }) { function DepartmentNodeMenu({ node, toggleDelete, toggleRename, toggleAddMembers, toggleAddDepartment, toggleAddLibrary }) {
return ( return (
<DropdownMenu <DropdownMenu
modifiers={{ preventOverflow: { boundariesElement: document.body } }} modifiers={[{ name: 'preventOverflow', options: { boundary: document.body } }]}
positionFixed={true} positionFixed={true}
> >
<DropdownItem key={`${node.id}-add-department`} onClick={() => toggleAddDepartment(node)}> <DropdownItem key={`${node.id}-add-department`} onClick={() => toggleAddDepartment(node)}>

View File

@ -119,7 +119,7 @@ class MemberItem extends React.Component {
aria-label={gettext('More operations')} aria-label={gettext('More operations')}
data-toggle="dropdown" data-toggle="dropdown"
/> />
<DropdownMenu right={true}> <DropdownMenu>
<DropdownItem onClick={this.toggleDeleteMemberDialog}>{gettext('Delete')}</DropdownItem> <DropdownItem onClick={this.toggleDeleteMemberDialog}>{gettext('Delete')}</DropdownItem>
</DropdownMenu> </DropdownMenu>
</Dropdown> </Dropdown>

View File

@ -123,7 +123,7 @@ class DingtalkDepartmentsTreeNode extends Component {
aria-expanded={this.state.dropdownOpen} aria-expanded={this.state.dropdownOpen}
> >
</DropdownToggle> </DropdownToggle>
<DropdownMenu className="drop-list" right={true}> <DropdownMenu className="drop-list">
<DropdownItem <DropdownItem
onClick={this.importDepartmentDialogToggle.bind(this, department)} onClick={this.importDepartmentDialogToggle.bind(this, department)}
id={department.id} id={department.id}

View File

@ -1,8 +1,8 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import MediaQuery from 'react-responsive'; import MediaQuery from 'react-responsive';
import { Modal } from 'reactstrap'; import { Modal } from 'reactstrap';
import { Router } from '@gatsbyjs/reach-router'; import { globalHistory, LocationProvider, Router } from '@gatsbyjs/reach-router';
import { I18nextProvider } from 'react-i18next'; import { I18nextProvider } from 'react-i18next';
import { siteRoot } from '../../utils/constants'; import { siteRoot } from '../../utils/constants';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
@ -287,9 +287,11 @@ class SysAdmin extends React.Component {
} }
} }
ReactDom.render( const root = createRoot(document.getElementById('wrapper'));
root.render(
<I18nextProvider value={i18n}> <I18nextProvider value={i18n}>
<LocationProvider history={globalHistory}>
<SysAdmin /> <SysAdmin />
</I18nextProvider>, </LocationProvider>
document.getElementById('wrapper') </I18nextProvider>
); );

View File

@ -56,7 +56,7 @@ class UsersFilterBar extends Component {
<div className="users-filter-bar mt-4 mb-2 d-flex"> <div className="users-filter-bar mt-4 mb-2 d-flex">
<Dropdown isOpen={this.state.isStatusOpen} toggle={this.toggleStatusDropdown}> <Dropdown isOpen={this.state.isStatusOpen} toggle={this.toggleStatusDropdown}>
<DropdownToggle <DropdownToggle
tag="div" tag="span"
data-toggle="dropdown" data-toggle="dropdown"
aria-expanded={this.state.isStatusOpen} aria-expanded={this.state.isStatusOpen}
className="users-filter-bar-dropdown-toggle" className="users-filter-bar-dropdown-toggle"
@ -78,7 +78,7 @@ class UsersFilterBar extends Component {
</Dropdown> </Dropdown>
<Dropdown isOpen={this.state.isRoleOpen} toggle={this.toggleRoleDropdown} className="ml-4"> <Dropdown isOpen={this.state.isRoleOpen} toggle={this.toggleRoleDropdown} className="ml-4">
<DropdownToggle <DropdownToggle
tag="div" tag="span"
data-toggle="dropdown" data-toggle="dropdown"
aria-expanded={this.state.isRoleOpen} aria-expanded={this.state.isRoleOpen}
className="users-filter-bar-dropdown-toggle" className="users-filter-bar-dropdown-toggle"

View File

@ -123,7 +123,7 @@ class WorkWeixinDepartmentsTreeNode extends Component {
aria-expanded={this.state.dropdownOpen} aria-expanded={this.state.dropdownOpen}
> >
</DropdownToggle> </DropdownToggle>
<DropdownMenu className="drop-list" right={true}> <DropdownMenu className="drop-list">
<DropdownItem <DropdownItem
onClick={this.importDepartmentDialogToggle.bind(this, department)} onClick={this.importDepartmentDialogToggle.bind(this, department)}
id={department.id} id={department.id}

View File

@ -1,5 +1,5 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import { gettext } from '../../utils/constants'; import { gettext } from '../../utils/constants';
@ -71,4 +71,5 @@ class SharedUploadLink extends React.Component {
} }
} }
ReactDom.render(<SharedUploadLink />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<SharedUploadLink />);

View File

@ -63,7 +63,7 @@ class UploadProgressDialog extends React.Component {
<Fragment> <Fragment>
<div className="text-center"> <div className="text-center">
<ButtonDropdown isOpen={this.state.dropdownOpen} toggle={this.toggleDropdown}> <ButtonDropdown isOpen={this.state.dropdownOpen} toggle={this.toggleDropdown}>
<DropdownToggle color="primary" caret onKeyDown={this.onDropdownToggleKeyDown}>{gettext('Upload')}</DropdownToggle> <DropdownToggle tag="span" color="primary" caret onKeyDown={this.onDropdownToggleKeyDown}>{gettext('Upload')}</DropdownToggle>
<DropdownMenu> <DropdownMenu>
<DropdownItem onClick={this.props.onFileUpload} onKeyDown={this.onMenuItemKeyDown}>{gettext('Upload Files')}</DropdownItem> <DropdownItem onClick={this.props.onFileUpload} onKeyDown={this.onMenuItemKeyDown}>{gettext('Upload Files')}</DropdownItem>
<DropdownItem onClick={this.props.onFolderUpload} onKeyDown={this.onMenuItemKeyDown}>{gettext('Upload Folder')}</DropdownItem> <DropdownItem onClick={this.props.onFolderUpload} onKeyDown={this.onMenuItemKeyDown}>{gettext('Upload Folder')}</DropdownItem>

View File

@ -97,7 +97,7 @@ export default class PageDropdownMenu extends Component {
<DropdownMenu <DropdownMenu
className="page-operation-dropdown-menu dtable-dropdown-menu large" className="page-operation-dropdown-menu dtable-dropdown-menu large"
flip={false} flip={false}
modifiers={{ preventOverflow: { boundariesElement: document.body } }} modifiers={[{ name: 'preventOverflow', options: { boundary: document.body } }]}
positionFixed={true} positionFixed={true}
> >
<DropdownItem onClick={this.handleCopyLink}> <DropdownItem onClick={this.handleCopyLink}>

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { navigate } from '@gatsbyjs/reach-router'; import { navigate } from '@gatsbyjs/reach-router';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
@ -442,4 +442,6 @@ FolderItem.propTypes = {
renderFolder: PropTypes.func.isRequired, renderFolder: PropTypes.func.isRequired,
}; };
ReactDom.render(<RepoFolderTrash />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<RepoFolderTrash />);

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { navigate } from '@gatsbyjs/reach-router'; import { navigate } from '@gatsbyjs/reach-router';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
@ -345,4 +345,5 @@ Item.propTypes = {
item: PropTypes.object.isRequired, item: PropTypes.object.isRequired,
}; };
ReactDom.render(<RepoHistory />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<RepoHistory />);

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { navigate } from '@gatsbyjs/reach-router'; import { navigate } from '@gatsbyjs/reach-router';
import { Utils } from './utils/utils'; import { Utils } from './utils/utils';
@ -319,4 +319,5 @@ FolderItem.propTypes = {
renderFolder: PropTypes.func.isRequired, renderFolder: PropTypes.func.isRequired,
}; };
ReactDom.render(<RepoSnapshot />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<RepoSnapshot />);

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import MediaQuery from 'react-responsive'; import MediaQuery from 'react-responsive';
import { Modal } from 'reactstrap'; import { Modal } from 'reactstrap';
import { Utils } from './utils/utils'; import { Utils } from './utils/utils';
@ -210,4 +210,5 @@ class Settings extends React.Component {
} }
} }
ReactDom.render(<Settings />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<Settings />);

View File

@ -1,7 +1,7 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import MD5 from 'MD5'; import MD5 from 'MD5';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import { Button, Dropdown, DropdownToggle, DropdownItem, UncontrolledTooltip } from 'reactstrap'; import { Button, Dropdown, DropdownToggle, DropdownItem, UncontrolledTooltip } from 'reactstrap';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime'; import relativeTime from 'dayjs/plugin/relativeTime';
@ -1015,4 +1015,5 @@ GridItem.propTypes = {
showImagePopup: PropTypes.func, showImagePopup: PropTypes.func,
}; };
ReactDom.render(<SharedDirView />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<SharedDirView />);

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import SharedFileView from './components/shared-file-view/shared-file-view'; import SharedFileView from './components/shared-file-view/shared-file-view';
import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip'; import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip';
import AudioPlayer from './components/audio-player'; import AudioPlayer from './components/audio-player';
@ -38,4 +38,5 @@ class FileContent extends React.Component {
} }
} }
ReactDom.render(<SharedFileViewAudio />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<SharedFileViewAudio />);

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import { seafileAPI } from './utils/seafile-api'; import { seafileAPI } from './utils/seafile-api';
import { gettext, mediaUrl } from './utils/constants'; import { gettext, mediaUrl } from './utils/constants';
import SharedFileView from './components/shared-file-view/shared-file-view'; import SharedFileView from './components/shared-file-view/shared-file-view';
@ -103,4 +103,5 @@ class FileContent extends React.Component {
} }
} }
ReactDom.render(<SharedFileViewDocument />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<SharedFileViewDocument />);

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import SharedFileView from './components/shared-file-view/shared-file-view'; import SharedFileView from './components/shared-file-view/shared-file-view';
import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip'; import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip';
import { gettext } from './utils/constants'; import { gettext } from './utils/constants';
@ -51,4 +51,5 @@ class FileContent extends React.Component {
} }
} }
ReactDom.render(<SharedFileViewImage />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<SharedFileViewImage />);

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import { MarkdownViewer } from '@seafile/seafile-editor'; import { MarkdownViewer } from '@seafile/seafile-editor';
import { seafileAPI } from './utils/seafile-api'; import { seafileAPI } from './utils/seafile-api';
import { Utils } from './utils/utils'; import { Utils } from './utils/utils';
@ -87,4 +87,5 @@ class FileContent extends React.Component {
} }
} }
ReactDom.render(<SharedFileViewMarkdown />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<SharedFileViewMarkdown />);

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import SharedFileView from './components/shared-file-view/shared-file-view'; import SharedFileView from './components/shared-file-view/shared-file-view';
import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip'; import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip';
import PDFViewer from './components/pdf-viewer'; import PDFViewer from './components/pdf-viewer';
@ -28,4 +28,5 @@ class FileContent extends React.Component {
} }
} }
ReactDom.render(<SharedFileViewPDF />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<SharedFileViewPDF />);

View File

@ -1,5 +1,5 @@
import React, { Suspense } from 'react'; import React, { Suspense } from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import { SimpleViewer } from '@seafile/sdoc-editor'; import { SimpleViewer } from '@seafile/sdoc-editor';
import { I18nextProvider } from 'react-i18next'; import { I18nextProvider } from 'react-i18next';
import i18n from './_i18n/i18n-sdoc-editor'; import i18n from './_i18n/i18n-sdoc-editor';
@ -44,11 +44,12 @@ window.seafile = {
document.getElementById('favicon').href = fileIcon; document.getElementById('favicon').href = fileIcon;
})(); })();
ReactDom.render(
const root = createRoot(document.getElementById('wrapper'));
root.render(
<I18nextProvider i18n={ i18n } > <I18nextProvider i18n={ i18n } >
<Suspense fallback={<Loading />}> <Suspense fallback={<Loading />}>
<SimpleViewer /> <SimpleViewer />
</Suspense> </Suspense>
</I18nextProvider>, </I18nextProvider>
document.getElementById('wrapper')
); );

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import { seafileAPI } from './utils/seafile-api'; import { seafileAPI } from './utils/seafile-api';
import { siteRoot, gettext } from './utils/constants'; import { siteRoot, gettext } from './utils/constants';
import SharedFileView from './components/shared-file-view/shared-file-view'; import SharedFileView from './components/shared-file-view/shared-file-view';
@ -105,4 +105,5 @@ class FileContent extends React.Component {
} }
} }
ReactDom.render(<SharedFileViewSpreadsheet />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<SharedFileViewSpreadsheet />);

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import SharedFileView from './components/shared-file-view/shared-file-view'; import SharedFileView from './components/shared-file-view/shared-file-view';
import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip'; import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip';
@ -29,4 +29,6 @@ class FileContent extends React.Component {
} }
} }
ReactDom.render(<SharedFileViewSVG />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<SharedFileViewSVG />);

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import SharedFileView from './components/shared-file-view/shared-file-view'; import SharedFileView from './components/shared-file-view/shared-file-view';
import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip'; import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip';
import SeafileCodeMirror from './components/seafile-codemirror'; import SeafileCodeMirror from './components/seafile-codemirror';
@ -27,4 +27,5 @@ class SharedFileViewText extends React.Component {
} }
} }
ReactDom.render(<SharedFileViewText />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<SharedFileViewText />);

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import SharedFileView from './components/shared-file-view/shared-file-view'; import SharedFileView from './components/shared-file-view/shared-file-view';
import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip'; import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip';
@ -19,4 +19,5 @@ class FileContent extends React.Component {
} }
} }
ReactDom.render(<SharedFileViewImage />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<SharedFileViewImage />);

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import SharedFileView from './components/shared-file-view/shared-file-view'; import SharedFileView from './components/shared-file-view/shared-file-view';
import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip'; import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip';
import VideoPlayer from './components/video-player'; import VideoPlayer from './components/video-player';
@ -40,4 +40,5 @@ class FileContent extends React.Component {
} }
} }
ReactDom.render(<SharedFileViewImage />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<SharedFileViewImage />);

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import { createRoot } from 'react-dom/client';
import { siteRoot, mediaUrl, logoPath, logoWidth, logoHeight, siteTitle } from './utils/constants'; import { siteRoot, mediaUrl, logoPath, logoWidth, logoHeight, siteTitle } from './utils/constants';
import SideNav from './components/user-settings/side-nav'; import SideNav from './components/user-settings/side-nav';
import Account from './components/common/account'; import Account from './components/common/account';
@ -66,7 +66,5 @@ class UserSubscription extends React.Component {
} }
} }
ReactDOM.render( const root = createRoot(document.getElementById('wrapper'));
<UserSubscription />, root.render(<UserSubscription />);
document.getElementById('wrapper')
);

View File

@ -44,7 +44,7 @@ const AllTagsOperationToolbar = ({ children }) => {
<div className="dir-operation"> <div className="dir-operation">
<Dropdown isOpen={isMenuOpen} toggle={toggleMenuOpen}> <Dropdown isOpen={isMenuOpen} toggle={toggleMenuOpen}>
<DropdownToggle <DropdownToggle
tag="div" tag="i"
role="button" role="button"
className="path-item" className="path-item"
onClick={toggleMenuOpen} onClick={toggleMenuOpen}

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDom from 'react-dom'; import { createRoot } from 'react-dom/client';
import { Button } from 'reactstrap'; import { Button } from 'reactstrap';
import { gettext } from './utils/constants'; import { gettext } from './utils/constants';
import Logo from './components/logo'; import Logo from './components/logo';
@ -48,4 +48,5 @@ class TCAccept extends React.Component {
} }
} }
ReactDom.render(<TCAccept />, document.getElementById('wrapper')); const root = createRoot(document.getElementById('wrapper'));
root.render(<TCAccept />);

Some files were not shown because too many files have changed in this diff Show More