Refactor organizations table to use fancy-table styles and InputClickToEdit
parent
f402faa936
commit
21cbd433c7
|
@ -67,15 +67,17 @@ class OrganizationsTable extends Component {
|
|||
</button>
|
||||
</div>
|
||||
<div className="panel-body">
|
||||
<div className="orgs-table--org-labels">
|
||||
<div className="orgs-table--active" />
|
||||
<div className="orgs-table--name">Name</div>
|
||||
<div className="orgs-table--public">
|
||||
<div className="fancytable--labels">
|
||||
<div className="fancytable--th orgs-table--active" />
|
||||
<div className="fancytable--th orgs-table--name">Name</div>
|
||||
<div className="fancytable--th orgs-table--public">
|
||||
Public{' '}
|
||||
<QuestionMarkTooltip tipID="public" tipContent={PUBLIC_TOOLTIP} />
|
||||
</div>
|
||||
<div className="orgs-table--default-role">Default Role</div>
|
||||
<div className="orgs-table--delete" />
|
||||
<div className="fancytable--th orgs-table--default-role">
|
||||
Default Role
|
||||
</div>
|
||||
<div className="fancytable--th orgs-table--delete" />
|
||||
</div>
|
||||
{isCreatingOrganization
|
||||
? <OrganizationsTableRowNew
|
||||
|
|
|
@ -6,6 +6,7 @@ import {withRouter} from 'react-router'
|
|||
import SlideToggle from 'shared/components/SlideToggle'
|
||||
import ConfirmButtons from 'shared/components/ConfirmButtons'
|
||||
import Dropdown from 'shared/components/Dropdown'
|
||||
import InputClickToEdit from 'shared/components/InputClickToEdit'
|
||||
|
||||
import {meChangeOrganizationAsync} from 'shared/actions/auth'
|
||||
|
||||
|
@ -32,9 +33,7 @@ class OrganizationsTableRow extends Component {
|
|||
super(props)
|
||||
|
||||
this.state = {
|
||||
isEditing: false,
|
||||
isDeleting: false,
|
||||
workingName: this.props.organization.name,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,55 +43,10 @@ class OrganizationsTableRow extends Component {
|
|||
await meChangeOrganization(links.me, {organization: organization.id})
|
||||
router.push('')
|
||||
}
|
||||
|
||||
handleNameClick = () => {
|
||||
this.setState({isEditing: true})
|
||||
handleUpdateOrgName = newName => {
|
||||
const {organization, onRename} = this.props
|
||||
onRename(organization, newName)
|
||||
}
|
||||
|
||||
handleConfirmRename = () => {
|
||||
const {onRename, organization} = this.props
|
||||
const {workingName} = this.state
|
||||
|
||||
onRename(organization, workingName)
|
||||
this.setState({workingName, isEditing: false})
|
||||
}
|
||||
|
||||
handleCancelRename = () => {
|
||||
const {organization} = this.props
|
||||
|
||||
this.setState({
|
||||
workingName: organization.name,
|
||||
isEditing: false,
|
||||
})
|
||||
}
|
||||
|
||||
handleInputChange = e => {
|
||||
this.setState({workingName: e.target.value})
|
||||
}
|
||||
|
||||
handleInputBlur = () => {
|
||||
const {organization} = this.props
|
||||
const {workingName} = this.state
|
||||
|
||||
if (organization.name === workingName) {
|
||||
this.handleCancelRename()
|
||||
} else {
|
||||
this.handleConfirmRename()
|
||||
}
|
||||
}
|
||||
|
||||
handleKeyDown = e => {
|
||||
if (e.key === 'Enter') {
|
||||
this.handleInputBlur()
|
||||
} else if (e.key === 'Escape') {
|
||||
this.handleCancelRename()
|
||||
}
|
||||
}
|
||||
|
||||
handleFocus = e => {
|
||||
e.target.select()
|
||||
}
|
||||
|
||||
handleDeleteClick = () => {
|
||||
this.setState({isDeleting: true})
|
||||
}
|
||||
|
@ -117,7 +71,7 @@ class OrganizationsTableRow extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const {workingName, isEditing, isDeleting} = this.state
|
||||
const {isDeleting} = this.state
|
||||
const {organization, currentOrganization} = this.props
|
||||
|
||||
const dropdownRolesItems = USER_ROLES.map(role => ({
|
||||
|
@ -126,12 +80,12 @@ class OrganizationsTableRow extends Component {
|
|||
}))
|
||||
|
||||
const defaultRoleClassName = isDeleting
|
||||
? 'orgs-table--default-role editing'
|
||||
: 'orgs-table--default-role'
|
||||
? 'fancytable--td orgs-table--default-role deleting'
|
||||
: 'fancytable--td orgs-table--default-role'
|
||||
|
||||
return (
|
||||
<div className="orgs-table--org">
|
||||
<div className="orgs-table--active">
|
||||
<div className="fancytable--row">
|
||||
<div className="fancytable--td orgs-table--active">
|
||||
{organization.id === currentOrganization.id
|
||||
? <button className="btn btn-sm btn-success">
|
||||
<span className="icon checkmark" /> Current
|
||||
|
@ -143,32 +97,22 @@ class OrganizationsTableRow extends Component {
|
|||
<span className="icon shuffle" /> Switch to
|
||||
</button>}
|
||||
</div>
|
||||
{isEditing
|
||||
? <input
|
||||
type="text"
|
||||
className="form-control input-sm orgs-table--input"
|
||||
defaultValue={workingName}
|
||||
onChange={this.handleInputChange}
|
||||
onBlur={this.handleInputBlur}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
placeholder="Name this Organization..."
|
||||
autoFocus={true}
|
||||
onFocus={this.handleFocus}
|
||||
ref={r => (this.inputRef = r)}
|
||||
/>
|
||||
: <div className="orgs-table--name" onClick={this.handleNameClick}>
|
||||
{workingName}
|
||||
<span className="icon pencil" />
|
||||
</div>}
|
||||
{organization.id === DEFAULT_ORG_ID
|
||||
? <div className="orgs-table--public">
|
||||
<SlideToggle
|
||||
size="xs"
|
||||
active={organization.public}
|
||||
onToggle={this.handleTogglePublic}
|
||||
/>
|
||||
</div>
|
||||
: <div className="orgs-table--public disabled">—</div>}
|
||||
<InputClickToEdit
|
||||
value={organization.name}
|
||||
wrapperClass="fancytable--td orgs-table--name"
|
||||
onUpdate={this.handleUpdateOrgName}
|
||||
/>
|
||||
<div className="fancytable--td orgs-table--public">
|
||||
{organization.id === DEFAULT_ORG_ID
|
||||
? <div className="orgs-table--public-toggle">
|
||||
<SlideToggle
|
||||
size="xs"
|
||||
active={organization.public}
|
||||
onToggle={this.handleTogglePublic}
|
||||
/>
|
||||
</div>
|
||||
: <div className="orgs-table--public-toggle disabled">—</div>}
|
||||
</div>
|
||||
<div className={defaultRoleClassName}>
|
||||
<Dropdown
|
||||
items={dropdownRolesItems}
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
import React, {PropTypes, Component} from 'react'
|
||||
|
||||
import SlideToggle from 'shared/components/SlideToggle'
|
||||
import Dropdown from 'shared/components/Dropdown'
|
||||
|
||||
import {USER_ROLES} from 'src/admin/constants/dummyUsers'
|
||||
|
||||
// This is a non-editable organization row, used currently for DEFAULT_ORG
|
||||
class OrganizationsTableRowDefault extends Component {
|
||||
togglePublic = () => {
|
||||
const {organization, onTogglePublic} = this.props
|
||||
onTogglePublic(organization)
|
||||
}
|
||||
|
||||
handleChooseDefaultRole = role => {
|
||||
const {organization, onChooseDefaultRole} = this.props
|
||||
onChooseDefaultRole(organization, role.name)
|
||||
}
|
||||
|
||||
render() {
|
||||
const {organization} = this.props
|
||||
|
||||
const dropdownRolesItems = USER_ROLES.map(role => ({
|
||||
...role,
|
||||
text: role.name,
|
||||
}))
|
||||
|
||||
return (
|
||||
<div className="fancytable--row">
|
||||
<div className="fancytable--td orgs-table--id">
|
||||
{organization.id}
|
||||
</div>
|
||||
<div className="fancytable--td orgs-table--name">
|
||||
{organization.name}
|
||||
</div>
|
||||
<div className="fancytable--td orgs-table--public">
|
||||
<div className="orgs-table--public-toggle">
|
||||
<SlideToggle
|
||||
size="xs"
|
||||
active={organization.public}
|
||||
onToggle={this.togglePublic}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="fancytable--td orgs-table--default-role">
|
||||
<Dropdown
|
||||
items={dropdownRolesItems}
|
||||
onChoose={this.handleChooseDefaultRole}
|
||||
selected={organization.defaultRole}
|
||||
className="dropdown-stretch"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
className="btn btn-sm btn-default btn-square orgs-table--delete"
|
||||
disabled={true}
|
||||
>
|
||||
<span className="icon trash" />
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const {func, shape, string} = PropTypes
|
||||
|
||||
OrganizationsTableRowDefault.propTypes = {
|
||||
organization: shape({
|
||||
id: string,
|
||||
name: string.isRequired,
|
||||
}).isRequired,
|
||||
onTogglePublic: func.isRequired,
|
||||
onChooseDefaultRole: func.isRequired,
|
||||
}
|
||||
|
||||
export default OrganizationsTableRowDefault
|
|
@ -58,20 +58,22 @@ class OrganizationsTableRowNew extends Component {
|
|||
}))
|
||||
|
||||
return (
|
||||
<div className="orgs-table--org orgs-table--new-org">
|
||||
<div className="orgs-table--active">—</div>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control input-sm orgs-table--input"
|
||||
value={name}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
onChange={this.handleInputChange}
|
||||
onFocus={this.handleInputFocus}
|
||||
placeholder="Name this Organization..."
|
||||
autoFocus={true}
|
||||
ref={r => (this.inputRef = r)}
|
||||
/>
|
||||
<div className="orgs-table--default-role editing">
|
||||
<div className="fancytable--row">
|
||||
<div className="fancytable--td orgs-table--active">—</div>
|
||||
<div className="fancytable--td orgs-table--name">
|
||||
<input
|
||||
type="text"
|
||||
className="form-control input-sm"
|
||||
value={name}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
onChange={this.handleInputChange}
|
||||
onFocus={this.handleInputFocus}
|
||||
placeholder="Name this Organization..."
|
||||
autoFocus={true}
|
||||
ref={r => (this.inputRef = r)}
|
||||
/>
|
||||
</div>
|
||||
<div className="fancytable--td orgs-table--default-role deleting">
|
||||
<Dropdown
|
||||
items={dropdownRolesItems}
|
||||
onChoose={this.handleChooseDefaultRole}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {DEFAULT_ORG} from 'src/admin/constants/dummyUsers'
|
||||
import {DEFAULT_ORG_ID} from 'src/admin/constants/chronografAdmin'
|
||||
|
||||
export const DEFAULT_PROVIDER_MAP_ID = '0'
|
||||
export const PROVIDER_MAPS = [
|
||||
|
@ -7,7 +7,7 @@ export const PROVIDER_MAPS = [
|
|||
scheme: '*',
|
||||
provider: '*',
|
||||
providerOrganization: '*',
|
||||
redirectOrg: {id: DEFAULT_ORG.id, name: DEFAULT_ORG.name},
|
||||
redirectOrg: {id: DEFAULT_ORG_ID, name: 'Default'},
|
||||
},
|
||||
{
|
||||
id: '1',
|
||||
|
|
|
@ -17,30 +17,35 @@ $fancytable--table--margin: 4px;
|
|||
}
|
||||
}
|
||||
.fancytable--row {
|
||||
margin-bottom: 8px;
|
||||
margin-bottom: $fancytable--table--margin;
|
||||
position: relative;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
.fancytable--td {
|
||||
height: 30px;
|
||||
}
|
||||
.fancytable--labels {
|
||||
border-bottom: 2px solid $g5-pepper;
|
||||
margin-bottom: 10px;
|
||||
@include no-user-select();
|
||||
}
|
||||
.fancytable--th {
|
||||
color: $g17-whisper;
|
||||
.fancytable--th,
|
||||
.fancytable--td {
|
||||
font-weight: 500;
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
font-size: 13px;
|
||||
}
|
||||
.fancytable--th {
|
||||
color: $g17-whisper;
|
||||
padding: 0 11px;
|
||||
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
.fancytable--td {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: $g13-mist;
|
||||
}
|
||||
|
|
|
@ -4,91 +4,41 @@
|
|||
Is not actually a table
|
||||
*/
|
||||
|
||||
.orgs-table--org {
|
||||
$orgs-table--active-width: 102px;
|
||||
$orgs-table--public-width: 90px;
|
||||
$orgs-table--default-role-width: 130px;
|
||||
$orgs-table--delete-width: 30px;
|
||||
|
||||
.orgs-table--name {
|
||||
flex: 1 0 0;
|
||||
}
|
||||
.orgs-table--public {
|
||||
width: $orgs-table--public-width;
|
||||
text-align: center;
|
||||
}
|
||||
.orgs-table--default-role {
|
||||
width: $orgs-table--default-role-width;
|
||||
}
|
||||
.orgs-table--delete {
|
||||
width: $orgs-table--delete-width;
|
||||
}
|
||||
.orgs-table--active {
|
||||
width: $orgs-table--active-width;
|
||||
}
|
||||
.orgs-table--default-role.deleting {
|
||||
width: (
|
||||
$orgs-table--default-role-width - $fancytable--table--margin -
|
||||
$orgs-table--delete-width
|
||||
);
|
||||
}
|
||||
.orgs-table--public-toggle {
|
||||
height: 30px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
position: relative;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
.orgs-table--id {
|
||||
padding: 0 11px;
|
||||
width: 60px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
font-size: 13px;
|
||||
color: $g13-mist;
|
||||
font-weight: 500;
|
||||
}
|
||||
.orgs-table--active {
|
||||
padding: 0 4px 0 0;
|
||||
width: 102px;
|
||||
height: 30px;
|
||||
|
||||
button.btn {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.orgs-table--name,
|
||||
.orgs-table--name-disabled,
|
||||
input[type="text"].form-control.orgs-table--input {
|
||||
flex: 1 0 0;
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.orgs-table--name,
|
||||
.orgs-table--name-disabled {
|
||||
@include no-user-select();
|
||||
padding: 0 11px;
|
||||
border-radius: 4px;
|
||||
height: 30px;
|
||||
line-height: 28px;
|
||||
border-style: solid;
|
||||
border-width: 2px;
|
||||
}
|
||||
.orgs-table--name {
|
||||
border-color: $g2-kevlar;
|
||||
background-color: $g2-kevlar;
|
||||
color: $g13-mist;
|
||||
position: relative;
|
||||
transition: color 0.4s ease, background-color 0.4s ease,
|
||||
border-color 0.4s ease;
|
||||
|
||||
> span.icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 11px;
|
||||
transform: translateY(-50%);
|
||||
color: $g8-storm;
|
||||
opacity: 0;
|
||||
transition: opacity 0.25s ease;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: $g20-white;
|
||||
background-color: $g5-pepper;
|
||||
border-color: $g5-pepper;
|
||||
cursor: text;
|
||||
|
||||
> span.icon {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.orgs-table--public {
|
||||
height: 30px;
|
||||
margin-right: 4px;
|
||||
text-align: center;
|
||||
width: 88px;
|
||||
justify-content: center;
|
||||
background-color: $g4-onyx;
|
||||
border-radius: 4px;
|
||||
line-height: 30px;
|
||||
position: relative;
|
||||
|
||||
> .slide-toggle {
|
||||
|
@ -103,69 +53,3 @@ input[type="text"].form-control.orgs-table--input {
|
|||
@include no-user-select();
|
||||
}
|
||||
}
|
||||
|
||||
.orgs-table--default-role,
|
||||
.orgs-table--default-role-disabled {
|
||||
width: 100px;
|
||||
height: 30px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.orgs-table--default-role.editing {
|
||||
width: 96px;
|
||||
}
|
||||
.orgs-table--default-role-disabled {
|
||||
background-color: $g4-onyx;
|
||||
font-style: italic;
|
||||
color: $g9-mountain;
|
||||
padding: 0 11px;
|
||||
line-height: 30px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
@include no-user-select();
|
||||
}
|
||||
.orgs-table--delete {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
/* Table Headers */
|
||||
.orgs-table--org-labels {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 2px solid $g5-pepper;
|
||||
margin-bottom: 10px;
|
||||
width: 100%;
|
||||
@include no-user-select();
|
||||
|
||||
> .orgs-table--name,
|
||||
> .orgs-table--name:hover,
|
||||
> .orgs-table--public,
|
||||
> .orgs-table--active {
|
||||
transition: none;
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
> .orgs-table--id,
|
||||
> .orgs-table--name,
|
||||
> .orgs-table--name:hover,
|
||||
> .orgs-table--default-role,
|
||||
> .orgs-table--public,
|
||||
> .orgs-table--active {
|
||||
color: $g17-whisper;
|
||||
font-weight: 500;
|
||||
}
|
||||
> .orgs-table--default-role,
|
||||
> .orgs-table--public,
|
||||
> .orgs-table--active {
|
||||
line-height: 30px;
|
||||
font-size: 13px;
|
||||
padding: 0 11px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Config table beneath organizations table */
|
||||
.panel .panel-body table.table.superadmin-config {
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
|
|
@ -4,25 +4,28 @@
|
|||
*/
|
||||
|
||||
$provider--id-width: 60px;
|
||||
$provider--scheme-width: 170px;
|
||||
$provider--provider-width: 170px;
|
||||
$provider--providerorg-width: 220px;
|
||||
$provider--scheme-width: 150px;
|
||||
$provider--provider-width: 150px;
|
||||
$provider--providerorg-width: 210px;
|
||||
$provider--redirect-width: 220px;
|
||||
$provider--delete-width: 30px;
|
||||
|
||||
.fancytable--td.provider--id,
|
||||
.fancytable--th.provider--id {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.provider--id {width: $provider--id-width;}
|
||||
.provider--scheme {width: $provider--scheme-width;}
|
||||
.provider--provider {width: $provider--provider-width;}
|
||||
.provider--providerorg {width: $provider--providerorg-width;}
|
||||
.provider--redirect {width: $provider--redirect-width;}
|
||||
.provider--delete {width: $provider--delete-width;}
|
||||
.provider--delete {
|
||||
width: $provider--delete-width;
|
||||
min-width: $provider--delete-width;
|
||||
}
|
||||
.provider--arrow {flex: 1 0 0;}
|
||||
|
||||
.fancytable--td.provider--id,
|
||||
.fancytable--th.provider--id {
|
||||
padding: 0 8px;
|
||||
}
|
||||
.provider--redirect.deleting {
|
||||
width: ($provider--redirect-width - $fancytable--table--margin - $provider--delete-width);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue