Merge branch 'master' of github.com:ONLYOFFICE/CommunityServer-AspNetCore
This commit is contained in:
commit
a2288468ff
@ -89,7 +89,12 @@ namespace ASC.Core.Caching
|
||||
{
|
||||
return (from == default(DateTime) ? users.Values : users.Values.Where(u => u.LastModified >= from)).ToDictionary(u => u.ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IDictionary<Guid, UserInfo> GetUsers(int tenant, bool isAdmin, EmployeeStatus? employeeStatus, List<Guid> includeGroups, List<Guid> excludeGroups, EmployeeActivationStatus? activationStatus, string text, string sortBy, bool sortOrderAsc, long limit, long offset, out int total)
|
||||
{
|
||||
return service.GetUsers(tenant, isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, text, sortBy, sortOrderAsc, limit, offset, out total);
|
||||
}
|
||||
|
||||
public UserInfo GetUser(int tenant, Guid id)
|
||||
{
|
||||
@ -411,7 +416,6 @@ namespace ASC.Core.Caching
|
||||
return tenant.ToString() + USERS + userId;
|
||||
}
|
||||
|
||||
|
||||
[Serializable]
|
||||
class UserPhoto
|
||||
{
|
||||
|
@ -85,7 +85,13 @@ namespace ASC.Core
|
||||
break;
|
||||
}
|
||||
return users.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<UserInfo> GetUsers(bool isAdmin, EmployeeStatus? employeeStatus, List<Guid> includeGroups, List<Guid> excludeGroups, EmployeeActivationStatus? activationStatus, string text, string sortBy, bool sortOrderAsc, long limit, long offset, out int total)
|
||||
{
|
||||
var tenantId = CoreContext.TenantManager.GetCurrentTenant().TenantId;
|
||||
return userService.GetUsers(tenantId, isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, text, sortBy, sortOrderAsc, limit, offset, out total).Values;
|
||||
}
|
||||
|
||||
public DateTime GetMaxUsersLastModified()
|
||||
{
|
||||
|
@ -33,6 +33,18 @@ namespace ASC.Core
|
||||
public interface IUserService
|
||||
{
|
||||
IDictionary<Guid, UserInfo> GetUsers(int tenant, DateTime from);
|
||||
|
||||
IDictionary<Guid, UserInfo> GetUsers(int tenant, bool isAdmin,
|
||||
EmployeeStatus? employeeStatus,
|
||||
List<Guid> includeGroups,
|
||||
List<Guid> excludeGroups,
|
||||
EmployeeActivationStatus? activationStatus,
|
||||
string text,
|
||||
string sortBy,
|
||||
bool sortOrderAsc,
|
||||
long limit,
|
||||
long offset,
|
||||
out int total);
|
||||
|
||||
UserInfo GetUser(int tenant, Guid id);
|
||||
|
||||
|
@ -24,16 +24,16 @@
|
||||
*/
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Common.Data.Sql;
|
||||
using ASC.Common.Data.Sql.Expressions;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Core.Users;
|
||||
using ASC.Security.Cryptography;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ASC.Core.Data
|
||||
{
|
||||
@ -50,6 +50,112 @@ namespace ASC.Core.Data
|
||||
return ExecList(q).ConvertAll(ToUser).ToDictionary(u => u.ID);
|
||||
}
|
||||
|
||||
public IDictionary<Guid, UserInfo> GetUsers(int tenant, bool isAdmin,
|
||||
EmployeeStatus? employeeStatus,
|
||||
List<Guid> includeGroups,
|
||||
List<Guid> excludeGroups,
|
||||
EmployeeActivationStatus? activationStatus,
|
||||
string text,
|
||||
string sortBy,
|
||||
bool sortOrderAsc,
|
||||
long limit,
|
||||
long offset,
|
||||
out int total)
|
||||
{
|
||||
var totalQuery = new SqlQuery("core_user u").Where("u.tenant", tenant).SelectCount();
|
||||
GetUserQueryForFilter(totalQuery, isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, text);
|
||||
total = ExecScalar<int>(totalQuery);
|
||||
|
||||
var q = GetUserQuery(tenant, default);
|
||||
|
||||
q = GetUserQueryForFilter(q, isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, text);
|
||||
|
||||
if (!string.IsNullOrEmpty(sortBy))
|
||||
{
|
||||
q.OrderBy(sortBy, sortOrderAsc);
|
||||
}
|
||||
|
||||
if(limit != 0)
|
||||
{
|
||||
q.SetMaxResults((int)limit);
|
||||
}
|
||||
|
||||
if(offset != 0)
|
||||
{
|
||||
q.SetFirstResult((int)offset);
|
||||
}
|
||||
|
||||
return ExecList(q).ConvertAll(ToUser).ToDictionary(u => u.ID);
|
||||
}
|
||||
|
||||
private SqlQuery GetUserQueryForFilter(SqlQuery q,bool isAdmin,
|
||||
EmployeeStatus? employeeStatus,
|
||||
List<Guid> includeGroups,
|
||||
List<Guid> excludeGroups,
|
||||
EmployeeActivationStatus? activationStatus,
|
||||
string text)
|
||||
{
|
||||
q.Where("u.removed", false);
|
||||
|
||||
if (includeGroups != null && includeGroups.Any())
|
||||
{
|
||||
foreach (var g in includeGroups)
|
||||
{
|
||||
var groupQuery = new SqlQuery("core_usergroup cug")
|
||||
.Where(Exp.EqColumns("cug.tenant", "cu.tenant"))
|
||||
.Where(Exp.EqColumns("cu.id", "cug.userid"))
|
||||
.Where(Exp.Eq("cug.groupid", g));
|
||||
q.Where(Exp.Exists(groupQuery));
|
||||
}
|
||||
}
|
||||
|
||||
if (excludeGroups != null && excludeGroups.Any())
|
||||
{
|
||||
foreach (var g in excludeGroups)
|
||||
{
|
||||
var groupQuery = new SqlQuery("core_usergroup cug")
|
||||
.Where(Exp.EqColumns("cug.tenant", "cu.tenant"))
|
||||
.Where(Exp.EqColumns("cu.id", "cug.userid"))
|
||||
.Where(Exp.Eq("cug.groupid", g));
|
||||
q.Where(!Exp.Exists(groupQuery));
|
||||
}
|
||||
}
|
||||
|
||||
if (employeeStatus != null)
|
||||
{
|
||||
switch (employeeStatus)
|
||||
{
|
||||
case EmployeeStatus.LeaveOfAbsence:
|
||||
case EmployeeStatus.Terminated:
|
||||
if (!isAdmin) q.Where("u.status", EmployeeStatus.Terminated);
|
||||
break;
|
||||
case EmployeeStatus.All:
|
||||
if (!isAdmin) q.Where("u.status", EmployeeStatus.Active);
|
||||
break;
|
||||
case EmployeeStatus.Default:
|
||||
case EmployeeStatus.Active:
|
||||
q.Where("u.status", EmployeeStatus.Active);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (activationStatus != null)
|
||||
{
|
||||
q.Where("u.activation_status", activationStatus.Value);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
{
|
||||
q.Where(Exp.Like("u.firstname", text, SqlLike.AnyWhere) |
|
||||
Exp.Like("u.lastname", text, SqlLike.AnyWhere) |
|
||||
Exp.Like("u.title", text, SqlLike.AnyWhere) |
|
||||
Exp.Like("u.location", text, SqlLike.AnyWhere) |
|
||||
Exp.Like("u.email", text, SqlLike.AnyWhere));
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
public UserInfo GetUser(int tenant, Guid id)
|
||||
{
|
||||
var q = GetUserQuery(tenant, default(DateTime)).Where("id", id);
|
||||
@ -329,11 +435,11 @@ namespace ASC.Core.Data
|
||||
var where = Exp.Empty;
|
||||
if (tenant != Tenant.DEFAULT_TENANT)
|
||||
{
|
||||
where &= Exp.Eq("tenant", tenant);
|
||||
where &= Exp.Eq("u.tenant", tenant);
|
||||
}
|
||||
if (from != default(DateTime))
|
||||
{
|
||||
where &= Exp.Ge("last_modified", from);
|
||||
where &= Exp.Ge("u.last_modified", from);
|
||||
}
|
||||
if (where != Exp.Empty)
|
||||
{
|
||||
|
@ -271,75 +271,40 @@ namespace ASC.Employee.Core.Controllers
|
||||
if (CoreContext.Configuration.Personal) throw new MethodAccessException("Method not available");
|
||||
var isAdmin = CoreContext.UserManager.GetUsers(SecurityContext.CurrentAccount.ID).IsAdmin() ||
|
||||
WebItemSecurity.IsProductAdministrator(WebItemManager.PeopleProductID, SecurityContext.CurrentAccount.ID);
|
||||
var status = isAdmin ? EmployeeStatus.All : EmployeeStatus.Default;
|
||||
|
||||
if (employeeStatus != null)
|
||||
var includeGroups = new List<Guid>();
|
||||
if (groupId.HasValue)
|
||||
{
|
||||
switch (employeeStatus)
|
||||
{
|
||||
case EmployeeStatus.Terminated:
|
||||
case EmployeeStatus.All:
|
||||
status = isAdmin ? (EmployeeStatus)employeeStatus : EmployeeStatus.Default;
|
||||
break;
|
||||
default:
|
||||
status = (EmployeeStatus)employeeStatus;
|
||||
break;
|
||||
}
|
||||
includeGroups.Add(groupId.Value);
|
||||
}
|
||||
|
||||
var users = string.IsNullOrEmpty(ApiContext.FilterValue) ?
|
||||
CoreContext.UserManager.GetUsers(status).AsEnumerable() :
|
||||
CoreContext.UserManager.Search(ApiContext.FilterValue, status).AsEnumerable();
|
||||
var excludeGroups = new List<Guid>();
|
||||
|
||||
if (groupId != null && !groupId.Equals(Guid.Empty))
|
||||
{
|
||||
users = users.Where(x => CoreContext.UserManager.IsUserInGroup(x.ID, (Guid)groupId));
|
||||
}
|
||||
if (activationStatus != null)
|
||||
{
|
||||
users = activationStatus == EmployeeActivationStatus.Activated ?
|
||||
users.Where(x => x.ActivationStatus.HasFlag(EmployeeActivationStatus.Activated)) :
|
||||
users.Where(x => x.ActivationStatus == EmployeeActivationStatus.NotActivated ||
|
||||
x.ActivationStatus == EmployeeActivationStatus.Pending ||
|
||||
x.ActivationStatus == EmployeeActivationStatus.AutoGenerated);
|
||||
}
|
||||
if (employeeType != null)
|
||||
{
|
||||
switch (employeeType)
|
||||
{
|
||||
case EmployeeType.User:
|
||||
users = users.Where(x => !x.IsVisitor());
|
||||
excludeGroups.Add(Constants.GroupVisitor.ID);
|
||||
break;
|
||||
case EmployeeType.Visitor:
|
||||
users = users.Where(x => x.IsVisitor());
|
||||
includeGroups.Add(Constants.GroupVisitor.ID);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isAdministrator.HasValue && isAdministrator.Value)
|
||||
{
|
||||
users = users.Where(x => x.IsAdmin() || x.GetListAdminModules().Any());
|
||||
includeGroups.Add(Constants.GroupAdmin.ID);
|
||||
|
||||
var products = WebItemManager.Instance.GetItemsAll().Where(i => i is IProduct || i.ID == WebItemManager.MailProductID);
|
||||
|
||||
includeGroups.AddRange(products.Select(r=> r.ID));
|
||||
}
|
||||
|
||||
ApiContext.TotalCount = users.Count();
|
||||
var users = CoreContext.UserManager.GetUsers(isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, ApiContext.FilterValue, ApiContext.SortBy, !ApiContext.SortDescending, ApiContext.Count - 1, ApiContext.StartIndex, out int total);
|
||||
|
||||
switch (ApiContext.SortBy)
|
||||
{
|
||||
case "firstname":
|
||||
users = ApiContext.SortDescending ? users.OrderByDescending(r => r, UserInfoComparer.FirstName) : users.OrderBy(r => r, UserInfoComparer.FirstName);
|
||||
break;
|
||||
case "lastname":
|
||||
users = ApiContext.SortDescending ? users.OrderByDescending(r => r, UserInfoComparer.LastName) : users.OrderBy(r => r, UserInfoComparer.LastName);
|
||||
break;
|
||||
default:
|
||||
users = ApiContext.SortDescending ? users.OrderByDescending(r => r, UserInfoComparer.Default) : users.OrderBy(r => r, UserInfoComparer.Default);
|
||||
break;
|
||||
}
|
||||
|
||||
users = users.Skip((int)ApiContext.StartIndex).Take((int)ApiContext.Count - 1);
|
||||
|
||||
//ApiContext.SetDataSorted();
|
||||
//ApiContext.SetDataPaginated();
|
||||
ApiContext.SetTotalCount(total);
|
||||
|
||||
return users;
|
||||
}
|
||||
|
@ -141,6 +141,7 @@ import OrigRadiobuttonHoverCheckedIcon from './radiobutton.hover.checked.react.s
|
||||
|
||||
import OrigToggleButtonCheckedIcon from './toggle.button.checked.react.svg';
|
||||
import OrigToggleButtonIcon from './toggle.button.react.svg';
|
||||
import OrigTabsIcon from './tabs.react.svg';
|
||||
|
||||
export const AZSortingIcon = createStyledIcon(
|
||||
OrigAZSortingIcon,
|
||||
@ -698,4 +699,10 @@ export const ToggleButtonIcon = createStyledIcon(
|
||||
OrigToggleButtonIcon,
|
||||
'ToggleButtonIcon',
|
||||
"rect"
|
||||
);
|
||||
|
||||
export const TabsIcon = createStyledIcon(
|
||||
OrigTabsIcon,
|
||||
'TabsIcon',
|
||||
"rect"
|
||||
);
|
@ -0,0 +1,3 @@
|
||||
<svg width="80" height="32" viewBox="0 0 80 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="80" height="32" rx="16" fill="#265A8F"/>
|
||||
</svg>
|
After Width: | Height: | Size: 157 B |
95
web/ASC.Web.Components/src/components/tabs/index.js
Normal file
95
web/ASC.Web.Components/src/components/tabs/index.js
Normal file
@ -0,0 +1,95 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled, { css } from 'styled-components';
|
||||
import { Icons } from '../icons';
|
||||
import { getCssFromSvg } from '../icons/get-css-from-svg';
|
||||
import ReactDOMServer from 'react-dom/server';
|
||||
|
||||
var tabsIcon/*, tabsIcon2*/;
|
||||
(function () { tabsIcon = getCssFromSvg(ReactDOMServer.renderToString(<Icons.TabsIcon />)); }());
|
||||
//tabsIcon2 = getCssFromSvg(ReactDOMServer.renderToString(<Icons.TabsIcon />));
|
||||
|
||||
// Основной контейнер
|
||||
const TabsContainer = styled.div``;
|
||||
|
||||
// Шапка
|
||||
const NavItem = styled.div`
|
||||
position: relative;
|
||||
box-shadow: 0px 5px 20px rgba(0,0,0,0.13);
|
||||
`;
|
||||
|
||||
//Исправить!!!
|
||||
const hoverCss = css`
|
||||
width: 80px;
|
||||
height: 32px;
|
||||
background-color: #F8F9F9;
|
||||
border-radius: 16px;
|
||||
`;
|
||||
|
||||
// Заголовки шапки
|
||||
const Label = styled.label`
|
||||
margin:0;
|
||||
min-width: 80px;
|
||||
position: relative;
|
||||
background-repeat: no-repeat;
|
||||
p {text-align: center; margin-top: 6px;}
|
||||
margin-right: 5px;
|
||||
label {margin:0}
|
||||
|
||||
${props => props.selected ?
|
||||
`background-image: url("data:image/svg+xml,${tabsIcon}"); cursor: default; p {color: #fff}` :
|
||||
`background-image: none;
|
||||
&:hover{
|
||||
cursor: pointer;
|
||||
${hoverCss}
|
||||
}`
|
||||
}
|
||||
`;
|
||||
|
||||
// Контенn в зависимости от шапки
|
||||
const BodyContainer = styled.div``;
|
||||
|
||||
|
||||
class Tabs extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
activeTab: '0'
|
||||
};
|
||||
}
|
||||
|
||||
labelClick = (tab) => {
|
||||
if (this.state.activeTab !== tab.id) {
|
||||
this.setState({ activeTab: tab.id });
|
||||
console.log('My update setState()');
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
//console.log(this.props.selected);
|
||||
return (
|
||||
<TabsContainer>
|
||||
<NavItem>
|
||||
{this.props.children.map((item) =>
|
||||
<Label
|
||||
selected={item.id === this.state.activeTab}
|
||||
key={item.id}
|
||||
onClick={() => {
|
||||
this.labelClick(item);
|
||||
}}>
|
||||
{item.title}
|
||||
</Label>
|
||||
)}
|
||||
</NavItem>
|
||||
<BodyContainer> {this.props.children[this.state.activeTab].body} </BodyContainer>
|
||||
</TabsContainer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Tabs;
|
||||
|
||||
Tabs.propTypes = {
|
||||
children: PropTypes.object
|
||||
};
|
||||
Tabs.defaultProps = {/*isChecked: false*/ };
|
@ -31,7 +31,7 @@ const HiddenInput = styled.input`
|
||||
z-index: -1;
|
||||
`;
|
||||
|
||||
const CheckboxIcon = ({ isChecked }) => {
|
||||
const ToggleIcon = ({ isChecked }) => {
|
||||
const iconName = isChecked ? "ToggleButtonCheckedIcon" : "ToggleButtonIcon";
|
||||
return <>{React.createElement(Icons[iconName])}</>;
|
||||
};
|
||||
@ -65,7 +65,7 @@ class ToggleButton extends Component {
|
||||
onChange={this.onInputChange}
|
||||
{...this.props}
|
||||
/>
|
||||
<CheckboxIcon {...this.props} />
|
||||
<ToggleIcon {...this.props} />
|
||||
{this.props.label && (
|
||||
<Text.Body
|
||||
tag="span"
|
||||
|
@ -40,3 +40,4 @@ export { default as RadioButton } from './components/radio-button'
|
||||
export { default as TextArea } from './components/text-area'
|
||||
export { default as ToggleButton } from './components/toggle-button'
|
||||
export { default as LinkWithDropdown } from './components/link-with-dropdown'
|
||||
export { default as Tabs } from './components/tabs'
|
||||
|
19
web/ASC.Web.Storybook/stories/tabs/README.md
Normal file
19
web/ASC.Web.Storybook/stories/tabs/README.md
Normal file
@ -0,0 +1,19 @@
|
||||
# Scrollbar
|
||||
|
||||
#### Description
|
||||
|
||||
Scrollbar is used for displaying custom scroollbar
|
||||
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
import { Scrollbar } from 'asc-web-components';
|
||||
|
||||
<Scrollbar>Some content</Scrollbar>
|
||||
```
|
||||
|
||||
#### Properties
|
||||
|
||||
| Props | Type | Required | Values | Default | Description |
|
||||
| ---------- | ----------- | :------: | ----------------------------------------- | ------------ | --------------------- |
|
||||
| `stype` | `string` | | `smallWhite`, `smallBlack`, `preMediumBlack`, `mediumBlack` | `smallBlack` | Scroollbar style type |
|
90
web/ASC.Web.Storybook/stories/tabs/index.stories.js
Normal file
90
web/ASC.Web.Storybook/stories/tabs/index.stories.js
Normal file
@ -0,0 +1,90 @@
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { withKnobs, boolean, text, select } from '@storybook/addon-knobs/react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import withReadme from 'storybook-readme/with-readme';
|
||||
import Readme from './README.md';
|
||||
import { Tabs, Text } from 'asc-web-components';
|
||||
import Section from '../../.storybook/decorators/section';
|
||||
import { BooleanValue } from 'react-values';
|
||||
|
||||
//<Text.Body tag="span">{text("Body text", "Try again later")}</Text.Body>
|
||||
|
||||
|
||||
const something_items = [
|
||||
{
|
||||
id: "0",
|
||||
title: <Text.Body> Title1 </Text.Body>,
|
||||
body:
|
||||
<div >
|
||||
<div> <button>BUTTON</button> <button>BUTTON</button> <button>BUTTON</button> </div>
|
||||
<div> <button>BUTTON</button> <button>BUTTON</button> <button>BUTTON</button> </div>
|
||||
<div> <button>BUTTON</button> <button>BUTTON</button> <button>BUTTON</button> </div>
|
||||
</div>
|
||||
},
|
||||
{
|
||||
id: "1",
|
||||
title: <Text.Body> Title2 </Text.Body>,
|
||||
body:
|
||||
<div >
|
||||
<div> <label>LABEL</label> <label>LABEL</label> <label>LABEL</label> </div>
|
||||
<div> <label>LABEL</label> <label>LABEL</label> <label>LABEL</label> </div>
|
||||
<div> <label>LABEL</label> <label>LABEL</label> <label>LABEL</label> </div>
|
||||
</div>
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: <Text.Body> Title3 </Text.Body>,
|
||||
body:
|
||||
<div>
|
||||
<div> <input></input> <input></input> <input></input> </div>
|
||||
<div> <input></input> <input></input> <input></input> </div>
|
||||
<div> <input></input> <input></input> <input></input> </div>
|
||||
</div>
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
title: <Text.Body> Title4 </Text.Body>,
|
||||
body:
|
||||
<div>
|
||||
<div> <button>BUTTON</button> <button>BUTTON</button> <button>BUTTON</button> </div>
|
||||
<div> <button>BUTTON</button> <button>BUTTON</button> <button>BUTTON</button> </div>
|
||||
<div> <button>BUTTON</button> <button>BUTTON</button> <button>BUTTON</button> </div>
|
||||
</div>
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
title: <Text.Body> Title5 </Text.Body>,
|
||||
body:
|
||||
<div>
|
||||
<div> <label>LABEL</label> <label>LABEL</label> <label>LABEL</label> </div>
|
||||
<div> <label>LABEL</label> <label>LABEL</label> <label>LABEL</label> </div>
|
||||
<div> <label>LABEL</label> <label>LABEL</label> <label>LABEL</label> </div>
|
||||
</div>
|
||||
}
|
||||
];
|
||||
/*
|
||||
const item = [{
|
||||
id: "0",
|
||||
something_title: <Text.Body>{text("Title text", "Title1")} </Text.Body>,
|
||||
something_body:
|
||||
<div >
|
||||
<div> <button>BUTTON</button> <button>BUTTON</button> <button>BUTTON</button> </div>
|
||||
<div> <button>BUTTON</button> <button>BUTTON</button> <button>BUTTON</button> </div>
|
||||
<div> <button>BUTTON</button> <button>BUTTON</button> <button>BUTTON</button> </div>
|
||||
</div>
|
||||
}];
|
||||
*/
|
||||
|
||||
storiesOf('Components|Tabs', module)
|
||||
.addDecorator(withKnobs)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add('base', () => {
|
||||
return (
|
||||
<BooleanValue>
|
||||
<Tabs>
|
||||
{something_items}
|
||||
</Tabs>
|
||||
</BooleanValue>
|
||||
);
|
||||
});
|
Loading…
Reference in New Issue
Block a user