Merge branch 'master' of https://github.com/ONLYOFFICE/CommunityServer-AspNetCore
This commit is contained in:
commit
2655a0fa52
15
build/tools/check.sh
Normal file
15
build/tools/check.sh
Normal file
@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
CHANGES=$(/snap/libxml2/current/bin/xmllint --xpath '//changeSet/item/affectedPath/text()' $1);
|
||||
shift
|
||||
for i in $CHANGES
|
||||
do
|
||||
for j in $@
|
||||
do
|
||||
if [[ $i == $j* ]]; then
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
exit 0
|
||||
|
5
config/nginx/onlyoffice-story.conf
Normal file
5
config/nginx/onlyoffice-story.conf
Normal file
@ -0,0 +1,5 @@
|
||||
server {
|
||||
listen 8081;
|
||||
root /var/www/story;
|
||||
index index.html;
|
||||
}
|
@ -1,95 +1,93 @@
|
||||
map $http_host $this_host {
|
||||
"" $host;
|
||||
default $http_host;
|
||||
}
|
||||
|
||||
map $http_x_forwarded_proto $the_scheme {
|
||||
default $http_x_forwarded_proto;
|
||||
"" $scheme;
|
||||
}
|
||||
|
||||
map $http_host $this_host {
|
||||
"" $host;
|
||||
default $http_host;
|
||||
map $http_x_forwarded_host $the_host {
|
||||
default $http_x_forwarded_host;
|
||||
"" $this_host;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 8092;
|
||||
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
|
||||
large_client_header_buffers 4 16k;
|
||||
|
||||
set $X_REWRITER_URL $the_scheme://$the_host;
|
||||
|
||||
if ($http_x_rewriter_url != '') {
|
||||
set $X_REWRITER_URL $http_x_rewriter_url ;
|
||||
}
|
||||
|
||||
fastcgi_read_timeout 600;
|
||||
fastcgi_send_timeout 600;
|
||||
fastcgi_keep_conn on;
|
||||
fastcgi_intercept_errors on;
|
||||
|
||||
map $http_x_forwarded_proto $the_scheme {
|
||||
default $http_x_forwarded_proto;
|
||||
"" $scheme;
|
||||
}
|
||||
include fastcgi_params;
|
||||
|
||||
map $http_x_forwarded_host $the_host {
|
||||
default $http_x_forwarded_host;
|
||||
"" $this_host;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 8092;
|
||||
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
|
||||
large_client_header_buffers 4 16k;
|
||||
|
||||
set $X_REWRITER_URL $the_scheme://$the_host;
|
||||
|
||||
if ($http_x_rewriter_url != '') {
|
||||
set $X_REWRITER_URL $http_x_rewriter_url ;
|
||||
}
|
||||
fastcgi_param HTTP_X_REWRITER_URL $http_x_rewriter_url;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO "";
|
||||
|
||||
fastcgi_read_timeout 600;
|
||||
fastcgi_send_timeout 600;
|
||||
fastcgi_keep_conn on;
|
||||
fastcgi_intercept_errors on;
|
||||
location / {
|
||||
proxy_pass http://localhost:5001;
|
||||
|
||||
location ~ /sockjs-node {
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header Host $host;
|
||||
|
||||
include fastcgi_params;
|
||||
proxy_pass http://localhost:5001;
|
||||
|
||||
fastcgi_param HTTP_X_REWRITER_URL $http_x_rewriter_url;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO "";
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:5001;
|
||||
|
||||
location ~ /sockjs-node {
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header Host $host;
|
||||
proxy_redirect off;
|
||||
|
||||
proxy_pass http://localhost:5001;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
|
||||
location ~ /api/2.0 {
|
||||
proxy_pass http://localhost:5000;
|
||||
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
|
||||
|
||||
proxy_redirect off;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
|
||||
location ~ /api/2.0 {
|
||||
proxy_pass http://localhost:5000;
|
||||
location ~ /people {
|
||||
proxy_pass http://localhost:5004;
|
||||
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
|
||||
|
||||
location ~ /people {
|
||||
proxy_pass http://localhost:5004;
|
||||
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
location /products {
|
||||
location ~ /people {
|
||||
#rewrite products/people/(.*) /$1 break;
|
||||
proxy_pass http://localhost:5002;
|
||||
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
|
||||
|
||||
location ~ /sockjs-node {
|
||||
rewrite products/people/(.*) /$1 break;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header Host $host;
|
||||
|
||||
location /products {
|
||||
location ~ /people {
|
||||
#rewrite products/people/(.*) /$1 break;
|
||||
proxy_pass http://localhost:5002;
|
||||
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
|
||||
|
||||
location ~ /sockjs-node {
|
||||
rewrite products/people/(.*) /$1 break;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header Host $host;
|
||||
|
||||
proxy_pass http://localhost:5002;
|
||||
proxy_redirect off;
|
||||
|
||||
proxy_redirect off;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
include /etc/nginx/includes/onlyoffice-*.conf;
|
@ -1,8 +1,9 @@
|
||||
import React, { Suspense } from 'react';
|
||||
import { BrowserRouter, Route, Switch } from 'react-router-dom';
|
||||
import { BrowserRouter, Switch } from 'react-router-dom';
|
||||
import { Loader, ErrorContainer } from 'asc-web-components';
|
||||
import PeopleLayout from './components/Layout';
|
||||
import Home from './components/pages/Home';
|
||||
import { PrivateRoute } from './helpers/privateRoute';
|
||||
var config = require('../package.json');
|
||||
|
||||
const App = () => {
|
||||
@ -11,8 +12,8 @@ const App = () => {
|
||||
<PeopleLayout>
|
||||
<Suspense fallback={<Loader className="pageLoader" type="rombs" size={40} />}>
|
||||
<Switch>
|
||||
<Route exact path={['/', config.homepage]} component={Home} />
|
||||
<Route component={() => (
|
||||
<PrivateRoute exact path={config.homepage} component={Home} />
|
||||
<PrivateRoute component={() => (
|
||||
<ErrorContainer>
|
||||
Sorry, the resource
|
||||
cannot be found.
|
||||
|
@ -3,10 +3,10 @@ import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withRouter } from "react-router";
|
||||
import { Layout } from 'asc-web-components';
|
||||
// import { logout } from '../../actions/authActions';
|
||||
import { logout } from '../actions/authActions';
|
||||
|
||||
const PeopleLayout = props => {
|
||||
const { auth, children, history } = props;
|
||||
const { auth, logout, children } = props;
|
||||
const currentUserActions = [
|
||||
{
|
||||
key: 'ProfileBtn', label: 'Profile', onClick: () => {
|
||||
@ -20,8 +20,7 @@ const PeopleLayout = props => {
|
||||
},
|
||||
{
|
||||
key: 'LogoutBtn', label: 'Log out', onClick: () => {
|
||||
//logout();
|
||||
history.push('/');
|
||||
logout();
|
||||
}
|
||||
},
|
||||
];
|
||||
@ -39,16 +38,46 @@ const PeopleLayout = props => {
|
||||
};
|
||||
|
||||
PeopleLayout.propTypes = {
|
||||
auth: PropTypes.object.isRequired
|
||||
auth: PropTypes.object.isRequired,
|
||||
logout: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
function convertModules(modules) {
|
||||
const separator = { seporator: true, id: 'nav-seporator-1' };
|
||||
const chat = {
|
||||
id: '22222222-2222-2222-2222-222222222222',
|
||||
title: 'Chat',
|
||||
iconName: 'ChatIcon',
|
||||
notifications: 3,
|
||||
url: '/products/chat/',
|
||||
onClick: () => window.open('/products/chat/', '_blank'),
|
||||
onBadgeClick: e => console.log('ChatIconBadge Clicked')(e),
|
||||
isolateMode: true
|
||||
};
|
||||
|
||||
let items = modules.map(item => {
|
||||
return {
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
title: item.title,
|
||||
iconName: 'PeopleIcon',
|
||||
notifications: 0,
|
||||
url: item.link,
|
||||
onClick: () => window.open(item.link, '_self'),
|
||||
onBadgeClick: e => console.log('PeopleIconBadge Clicked')(e)
|
||||
};
|
||||
}) || [];
|
||||
|
||||
return items.length ? [separator, ...items, chat] : items;
|
||||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
let availableModules = convertModules(state.auth.modules);
|
||||
return {
|
||||
auth: state.auth,
|
||||
availableModules: state.auth.modules,
|
||||
availableModules: availableModules,
|
||||
currentUser: state.auth.user,
|
||||
currentModuleId: state.auth.currentModuleId
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(withRouter(PeopleLayout));
|
||||
export default connect(mapStateToProps, { logout })(withRouter(PeopleLayout));
|
||||
|
@ -1,4 +1,7 @@
|
||||
import React, { useState } from "react";
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withRouter } from "react-router";
|
||||
import _ from 'lodash';
|
||||
import {
|
||||
PageLayout,
|
||||
@ -791,4 +794,17 @@ const Home = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default Home;
|
||||
Home.propTypes = {
|
||||
modules: PropTypes.array.isRequired,
|
||||
history: PropTypes.object.isRequired,
|
||||
isLoaded: PropTypes.bool
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
modules: state.auth.modules,
|
||||
isLoaded: state.auth.isLoaded
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(withRouter(Home));
|
||||
|
@ -1,12 +1,25 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import Cookies from 'universal-cookie';
|
||||
import setAuthorizationToken from './utils/setAuthorizationToken';
|
||||
import { AUTH_KEY } from './helpers/constants';
|
||||
import store from './store/store';
|
||||
import './custom.scss';
|
||||
import App from './App';
|
||||
import './i18n'
|
||||
|
||||
import * as serviceWorker from './serviceWorker';
|
||||
import { getUserInfo } from './actions/authActions';
|
||||
|
||||
var token = (new Cookies()).get(AUTH_KEY);
|
||||
|
||||
if (token) {
|
||||
setAuthorizationToken(token);
|
||||
store.dispatch(getUserInfo);
|
||||
}
|
||||
else
|
||||
throw new Error("Unauthorized");
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
|
@ -2,90 +2,11 @@ import { SET_CURRENT_USER, SET_MODULES, SET_IS_LOADED, LOGOUT } from '../actions
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
const initialState = {
|
||||
isAuthenticated: true,
|
||||
isLoaded: true,
|
||||
user: {
|
||||
id: '00000000-0000-0000-0000-000000000000',
|
||||
userName: 'Jane Doe',
|
||||
email: 'janedoe@gmail.com',
|
||||
isOwner: false,
|
||||
isAdmin: false,
|
||||
isVisitor: false,
|
||||
avatarSmall: '',
|
||||
avatarMedium: '',
|
||||
},
|
||||
currentModuleId: '11111111-1111-1111-1111-111111111111',
|
||||
modules: [
|
||||
{
|
||||
seporator: true,
|
||||
id: 'nav-seporator-1',
|
||||
},
|
||||
{
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
title: 'People',
|
||||
iconName: 'PeopleIcon',
|
||||
notifications: 0,
|
||||
url: '/products/people/',
|
||||
onClick: e => console.log('PeopleIcon Clicked', e),
|
||||
onBadgeClick: e => console.log('PeopleIconBadge Clicked', e),
|
||||
},
|
||||
{
|
||||
id: '22222222-2222-2222-2222-222222222222',
|
||||
title: 'Documents',
|
||||
iconName: 'DocumentsIcon',
|
||||
notifications: 2,
|
||||
url: '/products/documents/',
|
||||
onClick: e => console.log('DocumentsIcon Clicked', e),
|
||||
onBadgeClick: e => console.log('DocumentsIconBadge Clicked', e),
|
||||
},
|
||||
{
|
||||
id: '33333333-3333-3333-3333-333333333333',
|
||||
title: 'Chat',
|
||||
iconName: 'ChatIcon',
|
||||
notifications: 3,
|
||||
url: '/products/chat/',
|
||||
onClick: e => console.log('ChatIcon Clicked', e),
|
||||
isolateMode: true,
|
||||
},
|
||||
{
|
||||
id: '44444444-4444-4444-4444-444444444444',
|
||||
title: 'Mail',
|
||||
iconName: 'MailIcon',
|
||||
notifications: 7,
|
||||
url: '/products/mail/',
|
||||
onClick: e => console.log('MailIcon Clicked', e),
|
||||
onBadgeClick: e => console.log('MailIconBadge Clicked', e),
|
||||
},
|
||||
{
|
||||
id: '55555555-5555-5555-5555-555555555555',
|
||||
title: 'Projects',
|
||||
iconName: 'ProjectsIcon',
|
||||
notifications: 5,
|
||||
onClick: e => console.log('ProjectsIcon Clicked', e),
|
||||
onBadgeClick: e => console.log('ProjectsIconBadge Clicked', e),
|
||||
},
|
||||
{
|
||||
id: '77777777-7777-7777-7777-777777777777',
|
||||
title: 'CRM',
|
||||
iconName: 'CrmIcon',
|
||||
notifications: 0,
|
||||
onClick: e => console.log('CrmIcon Clicked', e),
|
||||
onBadgeClick: e => console.log('CrmIcon Clicked', e),
|
||||
},
|
||||
{
|
||||
seporator: true,
|
||||
id: 'nav-seporator-2',
|
||||
},
|
||||
{
|
||||
id: '66666666-6666-6666-6666-666666666666',
|
||||
title: 'Calendar',
|
||||
iconName: 'CalendarCheckedIcon',
|
||||
notifications: 0,
|
||||
onClick: e => console.log('CalendarIcon Clicked', e),
|
||||
onBadgeClick: e => console.log('CalendarIconBadge Clicked', e),
|
||||
},
|
||||
]
|
||||
}
|
||||
isAuthenticated: false,
|
||||
isLoaded: false,
|
||||
user: {},
|
||||
modules: []
|
||||
};
|
||||
|
||||
const auth = (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
|
@ -20,6 +20,8 @@ export default function setAuthorizationToken(token) {
|
||||
}
|
||||
else {
|
||||
delete axios.defaults.headers.common["Authorization"];
|
||||
cookies.remove(AUTH_KEY);
|
||||
cookies.remove(AUTH_KEY, {
|
||||
path: '/'
|
||||
});
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ const StudioLayout = props => {
|
||||
{
|
||||
key: 'AboutBtn', label: 'About', onClick: () => {
|
||||
console.log('AboutBtn');
|
||||
history.push('/about');
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -63,7 +64,7 @@ function convertModules(modules) {
|
||||
iconName: 'PeopleIcon',
|
||||
notifications: 0,
|
||||
url: item.link,
|
||||
onClick: () => window.open(item.link, '_blank'),
|
||||
onClick: () => window.open(item.link, '_self'),
|
||||
onBadgeClick: e => console.log('DocumentsIconBadge Clicked')(e)
|
||||
};
|
||||
}) || [];
|
||||
|
@ -13,7 +13,7 @@ const Tiles = ({ modules, isPrimary, history }) => {
|
||||
{
|
||||
modules.filter(m => m.isPrimary === isPrimary).map(module => (
|
||||
<Col key={++index}>
|
||||
<ModuleTile {...module} onClick={() => window.open(module.link, "_blank")} />
|
||||
<ModuleTile {...module} onClick={() => window.open(module.link, '_self')} />
|
||||
</Col>
|
||||
))
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
<svg width="33" height="26" viewBox="0 0 33 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0.5 3C0.5 1.61929 1.61929 0.5 3 0.5H21.1954C21.9785 0.5 22.7163 0.866919 23.1889 1.49134L31.2783 12.1803C31.6858 12.7188 31.6832 13.4633 31.2719 13.999L23.1913 24.5226C22.7182 25.1388 21.9854 25.5 21.2084 25.5H3C1.61929 25.5 0.5 24.3807 0.5 23V3Z" fill="#F8F9F9" stroke="#ECEEF1"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 12L6 12V14L12 14V20H14L14 14H20V12H14V6L12 6L12 12Z" fill="#A3A9AE"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 395 B After Width: | Height: | Size: 518 B |
@ -30,7 +30,7 @@ const StyledIconBlock = styled.div`
|
||||
const StyledChildrenBlock = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 2px;
|
||||
padding: 2px 0px 2px 2px;
|
||||
`;
|
||||
|
||||
const CustomInputGroup = ({ isIconFill, hasError, hasWarning, isDisabled, scale, ...props }) => (
|
||||
|
201
web/ASC.Web.Components/src/components/search-input/index.js
Normal file
201
web/ASC.Web.Components/src/components/search-input/index.js
Normal file
@ -0,0 +1,201 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import styled from 'styled-components';
|
||||
import InputBlock from '../input-block';
|
||||
import IconButton from '../icon-button';
|
||||
import ContextMenuButton from '../context-menu-button';
|
||||
|
||||
const StyledFilterItem = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
padding: 3px;
|
||||
margin-right: 2px;
|
||||
border: 1px solid #d4e4ec;
|
||||
border-radius: 3px;
|
||||
background-color: #edf6fd;
|
||||
`;
|
||||
const StyledIconButtonBlock = styled.div`
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
`;
|
||||
const FilterItem = props => {
|
||||
const { groupLabel, id, label } = props;
|
||||
return (
|
||||
<StyledFilterItem key={id}>
|
||||
{groupLabel} {label}
|
||||
<StyledIconButtonBlock>
|
||||
<IconButton
|
||||
color={props.color}
|
||||
size={10}
|
||||
iconName={"CrossIcon"}
|
||||
isFill={true}
|
||||
isDisabled={props.isDisabled}
|
||||
onClick={!props.isDisabled ? ((e) => props.onClose(e, id)) : undefined}
|
||||
/>
|
||||
</StyledIconButtonBlock>
|
||||
</StyledFilterItem>
|
||||
);
|
||||
};
|
||||
|
||||
class SearchInput extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
filterItems: []
|
||||
};
|
||||
|
||||
this.onClickDropDownItem = this.onClickDropDownItem.bind(this);
|
||||
this.getData = this.getData.bind(this);
|
||||
this.onSearchClick = this.onSearchClick.bind(this);
|
||||
this.onDeleteFilterItem = this.onDeleteFilterItem.bind(this);
|
||||
this.getFilterItems = this.getFilterItems.bind(this);
|
||||
|
||||
}
|
||||
|
||||
onClickDropDownItem(event, filterItem){
|
||||
|
||||
let curentFilterItems = this.state.filterItems.slice();
|
||||
let filterItems = this.getData()
|
||||
let indexFilterItem = curentFilterItems.findIndex(x => x.key === filterItem.group);
|
||||
if(indexFilterItem != -1){
|
||||
curentFilterItems.splice(indexFilterItem, 1);
|
||||
}
|
||||
|
||||
let selectFilterItem = {
|
||||
key: filterItem.group,
|
||||
value: filterItem.key,
|
||||
label: filterItem.label,
|
||||
groupLabel: filterItems.find(x => x.key === filterItem.group).label
|
||||
};
|
||||
curentFilterItems.push(selectFilterItem);
|
||||
|
||||
this.setState({ filterItems: curentFilterItems});
|
||||
if(typeof this.props.onChangeFilter === "function")
|
||||
this.props.onChangeFilter({
|
||||
inputValue: this.props.value,
|
||||
filterValue: this.props.isNeedFilter ? curentFilterItems : null
|
||||
});
|
||||
}
|
||||
|
||||
getData(){
|
||||
let _this = this;
|
||||
let d= this.props.getFilterData();
|
||||
d.map(function(item){
|
||||
item.onClick = !item.isSeparator && !item.isHeader && !item.disabled ? ((e) => _this.onClickDropDownItem(e, item)) : undefined;
|
||||
return item;
|
||||
});
|
||||
return d;
|
||||
}
|
||||
|
||||
onSearchClick(e, value){
|
||||
let searchResult = {
|
||||
inputValue: value,
|
||||
filterValue: this.props.isNeedFilter ? this.state.filterItems : null
|
||||
};
|
||||
if(typeof this.props.onSearchClick === "function")
|
||||
this.props.onSearchClick(searchResult);
|
||||
}
|
||||
|
||||
onDeleteFilterItem(e , key){
|
||||
|
||||
let curentFilterItems = this.state.filterItems.slice();
|
||||
let indexFilterItem = curentFilterItems.findIndex(x => x.key === key);
|
||||
if(indexFilterItem != -1){
|
||||
curentFilterItems.splice(indexFilterItem, 1);
|
||||
}
|
||||
this.setState({ filterItems: curentFilterItems});
|
||||
|
||||
if(typeof this.props.onChangeFilter === "function")
|
||||
this.props.onChangeFilter({
|
||||
inputValue: this.props.value,
|
||||
filterValue: this.props.isNeedFilter ? curentFilterItems : null
|
||||
});
|
||||
}
|
||||
|
||||
getFilterItems(){
|
||||
let _this = this;
|
||||
|
||||
const result = this.state.filterItems.map(function(item) {
|
||||
|
||||
return <FilterItem
|
||||
isDisabled={_this.props.isDisabled}
|
||||
key={item.key}
|
||||
id={item.key}
|
||||
groupLabel={item.groupLabel}
|
||||
label={item.label}
|
||||
onClose={_this.onDeleteFilterItem}>
|
||||
|
||||
</FilterItem>
|
||||
})
|
||||
return result;
|
||||
}
|
||||
|
||||
render() {
|
||||
let _this = this;
|
||||
let iconSize = 32;
|
||||
switch (this.props.size) {
|
||||
case 'base':
|
||||
iconSize = 32
|
||||
break;
|
||||
case 'middle':
|
||||
case 'big':
|
||||
case 'huge':
|
||||
iconSize = 41
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<InputBlock
|
||||
id={this.props.id}
|
||||
isDisabled={this.props.isDisabled}
|
||||
iconName={"SearchIcon"}
|
||||
isIconFill={true}
|
||||
iconColor={"#A3A9AE"}
|
||||
onIconClick={this.onSearchClick}
|
||||
size={this.props.size}
|
||||
scale={true}
|
||||
value={this.props.value}
|
||||
placeholder={this.props.placeholder}
|
||||
onChange={this.props.onChange}
|
||||
>
|
||||
{ this.props.isNeedFilter && this.getFilterItems()}
|
||||
{
|
||||
this.props.isNeedFilter &&
|
||||
<ContextMenuButton
|
||||
title={'Actions'}
|
||||
iconName={'RectangleFilterIcon'}
|
||||
color='#A3A9AE'
|
||||
size={iconSize}
|
||||
getData={_this.getData}
|
||||
/>
|
||||
}
|
||||
</InputBlock>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
SearchInput.propTypes = {
|
||||
id: PropTypes.string,
|
||||
size: PropTypes.oneOf(['base', 'middle', 'big', 'huge']),
|
||||
value:PropTypes.string,
|
||||
scale: PropTypes.bool,
|
||||
placeholder: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
getFilterData:PropTypes.func,
|
||||
isNeedFilter: PropTypes.bool,
|
||||
isDisabled: PropTypes.bool
|
||||
};
|
||||
|
||||
SearchInput.defaultProps = {
|
||||
size: 'base',
|
||||
value: '',
|
||||
scale: false,
|
||||
isNeedFilter: false,
|
||||
isDisabled: false
|
||||
};
|
||||
|
||||
export default SearchInput;
|
@ -25,4 +25,5 @@ export { default as Badge } from './components/badge'
|
||||
export { default as ErrorContainer } from './components/error-container'
|
||||
export { default as InputBlock } from './components/input-block'
|
||||
export { default as IconButton } from './components/icon-button'
|
||||
export { default as SearchInput } from './components/search-input'
|
||||
export { default as Backdrop } from './components/backdrop'
|
37
web/ASC.Web.Storybook/stories/input/search/README.md
Normal file
37
web/ASC.Web.Storybook/stories/input/search/README.md
Normal file
@ -0,0 +1,37 @@
|
||||
# Input: SearchInput
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import { SearchInput } from 'asc-web-components';
|
||||
```
|
||||
|
||||
#### Description
|
||||
|
||||
SearchInput description
|
||||
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
<SearchInput
|
||||
isNeedFilter={true}
|
||||
getFilterData={() => [ { key: 'filter-example', group: 'filter-example', label: 'example group', isHeader: true },
|
||||
{ key: 'filter-example-test', group: 'filter-example', label: 'Test' }]
|
||||
}
|
||||
onSearchClick={(result) => {console.log(result)}}
|
||||
onChangeFilter={(result) => {console.log(result)}}
|
||||
/>
|
||||
```
|
||||
|
||||
|
||||
| Props | Type | Required | Values | Default | Description |
|
||||
| ---------------------- | -------- | :------: | ---------------------------- | ------- | ------------------------------------------------------------------------------------------------------ |
|
||||
| `id` | `string` | - | - | - | Used as HTML `id` property |
|
||||
| `value` | `string` | - | - | - | Value of the input |
|
||||
| `onChange` | `func` | - | - | - | Called with the new value. Required when input is not read only. Parent should pass it back as `value` |
|
||||
| `isDisabled` | `bool` | - | - | `false` | Indicates that the field cannot be used (e.g not authorised, or changes not saved) |
|
||||
| `placeholder` | `string` | - | - | - | Placeholder text for the input |
|
||||
| `size` | `string` | | `base`, `middle`, `big`, `huge`| `base` | Supported size of the input fields. |
|
||||
| `scale` | `bool` | - | - | - | Indicates the input field has scale |
|
||||
| `isNeedFilter` | `bool` | | | `false` | Determines if filter is needed |
|
||||
|
55
web/ASC.Web.Storybook/stories/input/search/index.stories.js
Normal file
55
web/ASC.Web.Storybook/stories/input/search/index.stories.js
Normal file
@ -0,0 +1,55 @@
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { StringValue } from 'react-values';
|
||||
import { withKnobs, boolean, text, select, number } from '@storybook/addon-knobs/react';
|
||||
import withReadme from 'storybook-readme/with-readme';
|
||||
import Readme from './README.md';
|
||||
import { SearchInput } from 'asc-web-components';
|
||||
import Section from '../../../.storybook/decorators/section';
|
||||
|
||||
const sizeOptions = ['base', 'middle', 'big', 'huge'];
|
||||
function getData() {
|
||||
return [
|
||||
{ key: 'filter-status', group: 'filter-status', label: 'Status', isHeader: true },
|
||||
{ key: 'filter-status-active', group: 'filter-status', label: 'Active' },
|
||||
{ key: 'filter-status-disabled', group: 'filter-status', label: 'Disabled' },
|
||||
{ key: 'filter-type', group: 'filter-type', label: 'Type', isHeader: true },
|
||||
{ key: 'filter-type-administrator', group: 'filter-type', label: 'Administrator' },
|
||||
{ key: 'filter-type-employee', group: 'filter-type', label: 'Employee' },
|
||||
];
|
||||
}
|
||||
|
||||
storiesOf('Components|Input', module)
|
||||
.addDecorator(withKnobs)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add('search', () => (
|
||||
<Section>
|
||||
<StringValue
|
||||
onChange={e => {
|
||||
action('onChange')(e);
|
||||
}
|
||||
}
|
||||
>
|
||||
{({ value, set }) => (
|
||||
<Section>
|
||||
<SearchInput
|
||||
id={text('id', '')}
|
||||
isDisabled={boolean('isDisabled', false)}
|
||||
size={select('size', sizeOptions, 'base')}
|
||||
scale={boolean('scale', false)}
|
||||
isNeedFilter={boolean('isNeedFilter', true)}
|
||||
getFilterData={getData}
|
||||
placeholder={text('placeholder', 'Search')}
|
||||
onSearchClick={(result) => {console.log(result)}}
|
||||
onChangeFilter={(result) => {console.log(result)}}
|
||||
value={value}
|
||||
onChange={e => {
|
||||
set(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</Section>
|
||||
)}
|
||||
</StringValue>
|
||||
</Section>
|
||||
));
|
Loading…
Reference in New Issue
Block a user