Removing additional js files

This commit is contained in:
Romaric Mourgues
2023-04-20 11:52:18 +02:00
parent c515d5bad7
commit c4cd108a51
44 changed files with 29 additions and 3596 deletions
@@ -1,55 +0,0 @@
/* eslint-disable react/prop-types */
/* eslint-disable react/jsx-key */
import React, { Component } from 'react';
import './color-picker.scss';
import CheckIcon from '@material-ui/icons/CheckOutlined';
export default class ColorPicker extends Component {
static colors = [
'#D50000',
'#E67C73',
'#F4511E',
'#F6BF26',
'#33B679',
'#0B8043',
'#039BE5',
'#3F51B5',
'#7986CB',
'#8E24AA',
'#801515',
'#616161',
];
/*
props = {
value : default color
onChange : called when a color is selected
}
*/
constructor() {
super();
this.colors = ColorPicker.colors;
}
render() {
var showed_selected = this.colors.indexOf(this.props.value) >= 0;
var colors = this.colors;
if (!showed_selected) {
colors = this.colors.concat([this.props.value]);
}
return (
<div className="colorPicker" ref={this.props.refDom}>
{colors.map(color => {
return (
<div
className="color"
style={{ backgroundColor: color }}
onClick={() => this.props.onChange(color)}
>
{this.props.value == color && <CheckIcon className="m-icon-small" />}
</div>
);
})}
</div>
);
}
}
@@ -1,18 +0,0 @@
.colorPicker {
.color {
width: 16px;
height: 16px;
border-radius: var(--border-radius-large);
display: inline-block;
margin: 10px;
position: relative;
cursor: pointer;
.m-icon-small {
color: #fff;
width: 16px;
height: 16px;
position: absolute;
}
}
}
@@ -1,139 +0,0 @@
/* eslint-disable react/prop-types */
/* eslint-disable react/no-direct-mutation-state */
import React, { Component } from 'react';
import CloseIcon from '@material-ui/icons/CloseOutlined';
import AddIcon from '@material-ui/icons/AddOutlined';
import GearIcon from '@material-ui/icons/BuildOutlined';
import Input from 'components/inputs/input.jsx';
import './connectors-list-manager.scss';
import Languages from '@features/global/services/languages-service';
import WorkspacesApps from '@deprecated/workspaces/workspaces_apps.jsx';
import { getCompanyApplication as getApplication } from '@features/applications/state/company-applications';
export default class ConnectorsListManager extends Component {
constructor(props) {
super();
this.props = props;
this.state = {
connectors_ids: props.current.map(item => item.id || ''),
filtered: [],
input: '',
};
}
filter(text) {
this.state.input = text;
var list = this.props.list;
var res = list
.filter(el => {
return el.identity.name.toLocaleLowerCase().indexOf(text.toLocaleLowerCase()) >= 0;
})
.map(el => el);
this.setState({ filtered: res });
}
componentDidMount() {
this.filter('');
}
renderLine(item, added) {
var id = item.id || item;
item = getApplication(id);
var text = '';
var button = '';
text = (
<div className="text" style={{ display: 'flex', alignItems: 'center' }}>
{WorkspacesApps.getAppIconComponent(item)}
{item.identity.name}
</div>
);
if (added) {
button = (
<div className="more">
<GearIcon
className="m-icon-small config"
onClick={() => {
this.props.onConfig(item);
}}
/>
<CloseIcon
className="m-icon-small remove"
onClick={() => {
this.state.connectors_ids = this.state.connectors_ids.filter(id =>
typeof item == 'string' ? item != id : item.id != id,
);
this.setState({});
this.props.onChange(this.state.connectors_ids);
}}
/>
</div>
);
} else {
button = (
<div className="more">
<AddIcon
className="m-icon-small add"
onClick={() => {
this.state.connectors_ids.push(item.id || this.state.input.toLocaleLowerCase());
this.setState({ input: '' });
this.props.onChange(this.state.connectors_ids);
}}
/>
</div>
);
}
return (
<div className="menu no-background">
{text}
{button}
</div>
);
}
render() {
return (
<div className="connectorsListManager">
<div className="menu-title no-separator">
<div className="text">
{Languages.t('scenes.apps.tasks.connectors_menu', [], 'Connecteurs')}
</div>
</div>
{this.state.connectors_ids.length == 0 && (
<div className="menu-text">
{Languages.t('scenes.apps.tasks.no_connector', [], 'Aucun connecteurs.')}
</div>
)}
{this.state.connectors_ids.map(id => {
return this.renderLine(id, true);
})}
<div className="menu-title no-separator">
<div className="text">
{Languages.t('components.connectorslistmanager.add_connectors')}
</div>
</div>
<div className="menu-buttons" style={{ paddingTop: 2, paddingBottom: 2 }}>
<div className="text">
<Input
type="text"
className="small full_width bottom-margin"
placeholder={Languages.t('components.listmanager.filter', [], 'Filtrer')}
style={{ margin: 0 }}
onChange={evt => this.filter(evt.target.value)}
/>
</div>
</div>
{this.state.filtered.slice(0, 5).map(item => {
if (this.state.connectors_ids.indexOf(item.id) >= 0) {
return '';
}
return this.renderLine(item, false);
})}
</div>
);
}
}
@@ -1,49 +0,0 @@
.connectorsListManager {
margin: 0px -16px;
margin-top: -8px;
.menu-app-icon {
width: 18px;
height: 18px;
display: inline-block;
background-position: center;
background-size: contain;
border-radius: var(--border-radius-base);
vertical-align: middle;
margin-right: 8px;
}
.emoji-container {
margin-right: 5px;
top: 1px;
position: relative;
}
.menu-buttons {
padding: 0px 8px;
margin: 0px 8px;
}
.more {
width: auto !important;
margin-right: -5px;
.m-icon-small {
margin: 3px;
}
&:hover {
.m-icon-small {
&.remove:hover {
color: var(--red);
}
&.config:hover {
color: var(--primary);
}
&.add {
color: var(--primary);
}
}
}
}
}
@@ -1,74 +0,0 @@
import React, { Component } from 'react';
import InfiniteMessages from './infinite-messages.js';
export default class InfiniteMessagesTester extends Component {
constructor() {
super();
///////// Simulate messages
this.messages = [];
this.i = 0;
for (this.i; this.i < 10000; this.i++) {
this.messages.push({
content: 'message ' + this.i,
height: 40 + Math.random() * 100,
id: this.i,
});
}
setInterval(() => {
this.messages.push({
content: 'message ' + this.i,
height: 40 + Math.random() * 100,
id: this.i,
});
this.i++;
this.setState({});
}, 1000);
///////////
this.infinieMessages = null;
}
getMessages(offset, limit, callback) {
if (!offset) {
setTimeout(() => {
callback(this.messages.slice(this.messages.length - limit, this.messages.length));
}, 10);
} else {
var offsetPos = 0;
this.messages.every(m => {
if (m.id >= offset) {
return false;
}
offsetPos++;
return true;
});
setTimeout(() => {
if (limit > 0) {
callback(this.messages.slice(offsetPos - limit, offsetPos));
} else {
callback(this.messages.slice(offsetPos + 1, offsetPos - limit));
}
}, 10);
}
}
render() {
return (
<div className="infinite_messages_tester">
<InfiniteMessages
ref={node => (this.infinieMessages = node)}
getMessages={(offset, limit, callback) => this.getMessages(offset, limit, callback)}
messages={this.messages}
offsetKey={'id'}
top={''}
renderMessage={(message, oldmessage, measure) => (
<div className="message" style={{ height: message.height }}>
{message.content}
</div>
)}
/>
</div>
);
}
}
@@ -1,472 +0,0 @@
/* eslint-disable react/no-direct-mutation-state */
import React, { Component } from 'react';
import Button from 'components/buttons/button.jsx';
import './infinite-messages.scss';
export default class InfiniteMessages extends Component {
constructor(props) {
super(props);
window.test = this;
this.init(props);
this.onScroll = this.onScroll.bind(this);
this.onUpdate = this.onUpdate.bind(this);
}
init(props) {
props = props || this.props;
this.on_load_min = {};
if (props.messages.length > 60) {
this.on_load_min = props.messages.slice(props.messages.length - 60, props.messages.length)[0];
} else {
this.on_load_min = props.messages[0] || {};
}
this.state = {
messages: props.messages.filter(m => this.compare(m, this.on_load_min) >= 0),
};
this.shouldAutoScroll = true;
this.messages_min = this.state.messages[0] || {};
this.messages_med = this.state.messages[this.state.messages.length - 1] || {};
this.messages_max = this.state.messages[this.state.messages.length - 1] || {};
this.bloc_top_height = 0;
this.did_update_messages_data = {};
this.dom_messages = {};
this.max_known = this.messages_max;
}
componentDidMount() {
this.did_update_messages = true;
this.did_update_messages_data = {
direction: 'bottom_auto_add',
bloc_top_height: this.dom_visualized_messages_top.clientHeight,
bloc_bottom_height: this.dom_visualized_messages_bottom.clientHeight,
scroll_top: this.dom_infinite_messages.scrollTop,
scroll_height: this.dom_infinite_messages.scrollHeight,
};
// this.dom_infinite_messages.addEventListener("scroll", this.onScroll);
window.addEventListener('resize', this.onUpdate);
this.onUpdate();
}
componentWillUnmount() {
window.removeEventListener('resize', this.onUpdate);
// this.dom_infinite_messages.removeEventListener("scroll", this.onScroll);
}
UNSAFE_componentWillUpdate(nextProps, nextState) {
this.scroll_distance_from_bottom =
this.dom_infinite_messages.scrollHeight -
this.dom_infinite_messages.clientHeight -
this.dom_infinite_messages.scrollTop;
if (nextProps.messages.length) {
if (nextProps.messages[nextProps.messages.length - 1].id) {
if (this.messages_med.id == this.max_known.id) {
this.messages_med = nextProps.messages[nextProps.messages.length - 1];
this.messages_max = nextProps.messages[nextProps.messages.length - 1];
}
this.max_known = nextProps.messages[nextProps.messages.length - 1];
}
}
if (this.max_known.id == this.messages_med.id) {
nextState.messages = nextProps.messages.filter(m => {
return !m.id || this.compare(m, this.on_load_min) >= 0;
});
this.did_update_messages = true;
this.did_update_messages_data = {
direction: 'bottom_auto_add',
bloc_top_height: this.dom_visualized_messages_top.clientHeight,
bloc_bottom_height: this.dom_visualized_messages_bottom.clientHeight,
scroll_top: this.dom_infinite_messages.scrollTop,
scroll_height: this.dom_infinite_messages.scrollHeight,
};
}
}
componentDidUpdate() {
this.onUpdate();
}
onUpdate() {
this.did_auto_scroll = new Date();
this.scrollToBottom();
var dom_fake_separator_top_visible = Math.max(
0,
this.dom_infinite_messages.clientHeight - this.dom_visualized_messages_top.clientHeight,
);
if (dom_fake_separator_top_visible == 0) {
this.dom_fake_separator_top.style.display = 'none';
} else {
this.dom_fake_separator_top.style.display = 'block';
}
if (this.did_update_messages) {
this.did_update_messages = false;
this.bloc_top_height = this.dom_visualized_messages_top.clientHeight;
this.bloc_bottom_height = this.dom_visualized_messages_bottom.clientHeight;
if (this.did_update_messages_data.direction == 'bottom') {
this.scrollToPosition(
this.dom_anything_on_top.clientHeight +
(this.did_update_messages_data.bloc_bottom_height -
(this.did_update_messages_data.scroll_height -
this.did_update_messages_data.scroll_top)),
);
} else if (this.did_update_messages_data.direction == 'bottom_auto_add') {
//Nothing
} else {
this.scrollToPosition(this.bloc_top_height + this.did_update_messages_data.scroll_top);
}
this.getVisibleMessages();
}
}
onScroll(evt) {
if (new Date() - this.did_auto_scroll < 100) {
return;
}
if (
this.dom_infinite_messages.scrollHeight != this.last_scrollHeight &&
this.shouldAutoScroll
) {
this.last_scrollHeight = this.dom_infinite_messages.scrollHeight;
this.scrollToBottom();
} else {
var shouldAutoScroll = this.shouldAutoScroll;
this.shouldAutoScroll = false;
if (this.props.onAutoScrollChange && shouldAutoScroll) this.props.onAutoScrollChange(false);
}
if (this.dom_infinite_messages.scrollTop <= this.dom_infinite_messages.scrollHeight / 8) {
this.onScrollTop();
}
var dist_from_bottom =
this.dom_infinite_messages.scrollHeight -
this.dom_infinite_messages.scrollTop -
this.dom_infinite_messages.clientHeight;
if (dist_from_bottom <= Math.max(10, this.dom_infinite_messages.scrollHeight / 8)) {
if (
dist_from_bottom <= 10 &&
(this.shouldAutoScroll ||
this.max_known.id == this.state.messages[this.state.messages.length - 1].id)
) {
// eslint-disable-next-line no-redeclare
var shouldAutoScroll = this.shouldAutoScroll;
this.shouldAutoScroll = true;
if (this.props.onAutoScrollChange && !shouldAutoScroll) this.props.onAutoScrollChange(true);
} else if (dist_from_bottom <= 10 || this.max_known.id != this.messages_med.id) {
this.onScrollBottom();
}
}
this.getVisibleMessages();
}
getVisibleMessages() {
if (
this.last_get &&
Math.abs(this.last_get.scroll_top - this.dom_infinite_messages.scrollTop) < 40
) {
return [this.last_get.first];
}
var first = null;
var frame = window.getBoundingClientRect(this.dom_infinite_messages);
frame.x = frame.x || frame.left;
frame.y = frame.y || frame.top;
frame.scrollTop = this.dom_infinite_messages.scrollTop;
Object.keys(this.dom_messages).every(i => {
var item = this.dom_messages[i];
if (item.node && item.scrollTop === undefined) {
item.scrollTop = window.getBoundingClientRect(item.node).top + frame.scrollTop - frame.y;
}
if (item.node) {
if (!first && item.scrollTop > frame.scrollTop) {
first = item.message;
return false;
}
}
return true;
});
var first_date = new Date((first || {}).creation_date * 1000).setHours(0, 0, 0, 0);
if (first_date != (this.last_get || {}).first_date) {
if (this.props.onFirstDateChange) this.props.onFirstDateChange(first_date);
}
this.last_get = {
scroll_top: frame.scrollTop,
first: first,
first_date: first_date,
};
return [this.last_get.first];
}
scrollToBottom(force) {
if (this.shouldAutoScroll || force) {
//Make sure we display the last bloc !
if (
this.messages_med.id != this.messages_min.id &&
this.messages_med.id != this.messages_max.id
) {
this.init();
this.did_update_messages = true;
this.did_update_messages_data = {
direction: 'bottom_auto_add',
bloc_top_height: this.dom_visualized_messages_top.clientHeight,
bloc_bottom_height: this.dom_visualized_messages_bottom.clientHeight,
scroll_top: this.dom_infinite_messages.scrollTop,
scroll_height: this.dom_infinite_messages.scrollHeight,
};
this.onUpdate();
}
var old_position = this.dom_infinite_messages.scrollTop;
this.dom_infinite_messages.scrollTop = this.dom_infinite_messages.scrollHeight;
if (old_position != this.dom_infinite_messages.scrollTop) {
this.did_auto_scroll = new Date();
}
var shouldAutoScroll = this.shouldAutoScroll;
this.shouldAutoScroll = true;
if (this.props.onAutoScrollChange && !shouldAutoScroll) this.props.onAutoScrollChange(true);
}
}
scrollToPosition(scrollTop) {
var old_position = this.dom_infinite_messages.scrollTop;
this.dom_infinite_messages.scrollTop = scrollTop;
this.did_auto_scroll = new Date();
}
onScrollTop() {
if (this.is_getting_top_messages) {
return;
}
if (this.no_more_before && this.messages_min.id == this.no_more_before.id) {
return;
}
this.number_of_messages_to_load = 2 * (this.dom_infinite_messages.clientHeight / 20);
this.is_getting_top_messages = true;
this.props.getMessages(this.messages_min.id, parseInt(this.number_of_messages_to_load), res => {
if (res.length == 0) {
this.is_getting_top_messages = false;
this.no_more_before = this.messages_min;
return;
}
var top_list = this.state.messages.filter(
m => this.compare(m, this.messages_min) >= 0 && this.compare(m, this.messages_med) <= 0,
);
top_list = res.concat(top_list);
this.messages_med = res[res.length - 1];
this.messages_min = res[0];
this.messages_max = top_list[top_list.length - 1];
this.did_update_messages = true;
this.did_update_messages_data = {
direction: 'top',
bloc_top_height: this.dom_visualized_messages_top.clientHeight,
bloc_bottom_height: this.dom_visualized_messages_bottom.clientHeight,
scroll_top: this.dom_infinite_messages.scrollTop,
scroll_height: this.dom_infinite_messages.scrollHeight,
};
this.dom_messages = {};
this.setState({ messages: top_list });
this.is_getting_top_messages = false;
});
}
onScrollBottom() {
if (this.is_getting_bottom_messages) {
return;
}
this.number_of_messages_to_load = 2 * (this.dom_infinite_messages.clientHeight / 20);
this.is_getting_bottom_messages = true;
this.props.getMessages(
this.messages_max.id,
-parseInt(this.number_of_messages_to_load),
res => {
if (res.length == 0) {
this.is_getting_bottom_messages = false;
var shouldAutoScroll = this.shouldAutoScroll;
this.shouldAutoScroll = true;
if (this.props.onAutoScrollChange && !shouldAutoScroll)
this.props.onAutoScrollChange(true);
this.max_known = this.state.messages[this.state.messages.length - 1];
this.messages_min = this.state.messages[0];
this.messages_max = this.state.messages[this.state.messages.length - 1];
this.messages_med = this.messages_max;
return;
}
if (this.compare(res[res.length - 1], this.on_load_min) >= 0) {
var top_list = this.state.messages.filter(m => this.compare(m, res[res.length - 1]) >= 0);
top_list = top_list.concat(res);
this.state.messages = this.props.messages.filter(
m => this.compare(m, this.on_load_min) > 0,
);
this.max_known = this.state.messages[this.state.messages.length - 1];
this.messages_min = this.state.messages[0];
this.messages_max = this.state.messages[this.state.messages.length - 1];
this.messages_med = this.messages_max;
this.did_update_messages = true;
this.did_update_messages_data = {
direction: 'bottom_auto_add',
bloc_top_height: this.dom_visualized_messages_top.clientHeight,
bloc_bottom_height: this.dom_visualized_messages_bottom.clientHeight,
scroll_top: this.dom_infinite_messages.scrollTop,
scroll_height: this.dom_infinite_messages.scrollHeight,
};
this.dom_messages = {};
this.setState({ messages: this.state.messages });
} else {
// eslint-disable-next-line no-redeclare
var top_list = this.state.messages.filter(
m => this.compare(m, this.messages_med) > 0 && this.compare(m, this.messages_max) <= 0,
);
top_list = top_list.concat(res);
this.messages_min = top_list[0];
this.messages_med = this.messages_max;
this.messages_max = top_list[top_list.length - 1];
this.did_update_messages = true;
this.did_update_messages_data = {
direction: 'bottom',
bloc_top_height: this.dom_visualized_messages_top.clientHeight,
bloc_bottom_height: this.dom_visualized_messages_bottom.clientHeight,
scroll_top: this.dom_infinite_messages.scrollTop,
scroll_height: this.dom_infinite_messages.scrollHeight,
};
this.dom_messages = {};
this.setState({ messages: top_list });
}
this.is_getting_bottom_messages = false;
},
);
}
measure(message) {
if (this.dom_infinite_messages) {
this.scrollToBottom();
}
}
//Returns a-b as int
compare(a, b) {
if (this.props.compare) {
return this.props.compare(a, b);
}
return a.id - b.id;
}
render() {
var previous_message = null;
return (
<div className="infinite_messages" ref={node => (this.dom_infinite_messages = node)}>
<div ref={node => (this.dom_anything_on_top = node)}>
{this.props.top || ''}
{!this.no_more_before && (
<div style={{ textAlign: 'center' }}>
<Button
className="small primary"
onClick={() => {
this.onScrollTop();
}}
>
Load more messages
</Button>
</div>
)}
</div>
<div className="fake_separator_top" ref={node => (this.dom_fake_separator_top = node)} />
<div
className="visualized_messages top"
ref={node => (this.dom_visualized_messages_top = node)}
>
{this.state.messages.map((message, _i) => {
if (this.compare(message, this.messages_med) <= 0) {
var tmp = previous_message;
previous_message = message;
var i = _i;
return (
<div
key={message.id}
ref={node =>
(this.dom_messages[i] = {
node: node,
message: message,
scrollTop: (this.dom_messages[i] || {}).scrollTop,
})
}
>
{this.props.renderMessage(message, tmp, () => this.measure(message))}
</div>
);
}
})}
</div>
<div
className="visualized_messages"
ref={node => (this.dom_visualized_messages_bottom = node)}
>
{this.state.messages.map((message, _i) => {
if (this.compare(message, this.messages_med) > 0) {
var tmp = previous_message;
previous_message = message;
var i = _i;
return (
<div
key={message.id}
ref={node =>
(this.dom_messages[i] = {
node: node,
message: message,
scrollTop: (this.dom_messages[i] || {}).scrollTop,
})
}
>
{this.props.renderMessage(message, tmp, () => this.measure(message))}
</div>
);
}
})}
</div>
</div>
);
}
}
@@ -1,31 +0,0 @@
.infinite_messages {
overflow: auto;
flex: 1;
display: flex;
flex-direction: column;
.message {
box-sizing: border-box;
}
.fake_separator_top {
background: transparent;
flex: 1;
}
}
.infinite_messages_tester {
height: 90vh;
display: flex;
width: 100%;
.message {
box-sizing: border-box;
border: 1px solid #f00;
border-bottom: 5px solid #0f0;
}
.visualized_messages.top {
.message {
background: #fee;
}
}
}
@@ -1,28 +0,0 @@
import React, { Component } from 'react';
import './inline-tag-picker.scss';
export default class InlineTagPicker extends Component {
render() {
return this.props.available.map(item => {
return (
<div
key={item}
className={
'inline-tag small-top-margin ' + (this.props.value.includes(item) ? 'selected' : '')
}
onClick={() => {
let array = (this.props.value || []).map(a => a);
if (this.props.value.includes(item)) {
array = this.props.value.filter(val => item !== val);
} else {
array.push(item);
}
this.props.onChange(array);
}}
>
{item}
</div>
);
});
}
}
@@ -1,23 +0,0 @@
.inline-tag {
cursor: pointer;
background: var(--grey-light);
border-radius: var(--border-radius-base);
height: 20px;
color: var(--grey-dark);
font-size: 12px;
padding: 0 5px;
line-height: 18px;
box-sizing: border-box;
width: auto;
display: inline-block;
margin-right: 6px;
font-weight: normal;
&.selected {
background: var(--green);
color: var(--white);
}
&:hover {
transition: 0.3s;
opacity: 0.9;
}
}
@@ -1,59 +0,0 @@
/* eslint-disable react/prop-types */
import React, { Component } from 'react';
import Languages from '@features/global/services/languages-service';
import Tooltip from 'components/tooltip/tooltip.jsx';
import InputWithButton from 'components/inputs/input-with-button.jsx';
export default class InputWithClipBoard extends Component {
/*
props = {
value : "",
disabled : true|false
}
*/
constructor(props) {
super(props);
this.props = props;
this.state = {
i18n: Languages,
};
Languages.addListener(this);
this.inputElement = false;
}
componentWillUnmount() {
Languages.removeListener(this);
}
selectAll() {
this.inputElement.focus();
this.inputElement.select();
}
copy() {
this.inputElement.disabled = false;
this.inputElement.focus();
this.inputElement.select();
document.execCommand('copy');
this.inputElement.disabled = this.props.disabled;
this.tooltip.openWithTimeOut(2);
}
render() {
return (
<Tooltip
ref={obj => (this.tooltip = obj)}
overable={false}
tooltip={Languages.t('components.input.copied', [], 'Copié')}
>
<InputWithButton
refInput={obj => (this.inputElement = obj)}
btnAction={() => this.copy()}
icon="copy"
hideBtn={this.props.hideBtn}
value={this.props.value}
disabled={this.props.disabled}
/>
</Tooltip>
);
}
}
@@ -1,95 +0,0 @@
/* eslint-disable react/prop-types */
import React, { Component } from 'react';
import './inputs.scss';
import CheckIcon from '@material-ui/icons/CheckOutlined';
export default class Checkbox extends Component {
constructor() {
super();
}
renderSwitch() {
var className = this.props.className || '';
if (this.props.big) {
className += ' big ';
}
if (this.props.medium) {
className += ' medium ';
}
if (this.props.small) {
className += ' small ';
}
if (
className.indexOf('medium') === className.indexOf('small') &&
className.indexOf('big') === className.indexOf('small') &&
className.indexOf('big') < 0
) {
className += ' medium';
}
return (
<div
className={
' flex justify-center items-center w-6 h-6 border-2 rounded-full text-white ' +
(this.props.value
? 'border-blue-500 bg-blue-500 hover:border-blue-600 hover:bg-blue-600'
: 'border-zinc-300 hover:border-blue-300') +
' ' +
(this.props.disabled ? 'opacity-50' : 'cursor-pointer') +
' ' +
(className || '')
}
onClick={() => {
if (!this.props.label && !this.props.disabled) {
this.props.onChange(!this.props.value);
}
}}
>
<div className="state">
<CheckIcon className="m-icon-small" />
</div>
</div>
);
}
render() {
var parentClassName = '';
if (this.props.big) {
parentClassName += ' big ';
}
if (this.props.medium) {
parentClassName += ' medium ';
}
if (this.props.small) {
parentClassName += ' small ';
}
if (
parentClassName.indexOf('medium') === parentClassName.indexOf('small') &&
parentClassName.indexOf('big') === parentClassName.indexOf('small') &&
parentClassName.indexOf('big') < 0
) {
parentClassName += ' medium';
}
if (this.props.label) {
return (
<div
className={'checkbox_with_label ' + (this.props.value ? 'on ' : 'off ') + parentClassName}
onClick={() => {
if (!this.props.disabled) {
this.props.onChange(!this.props.value);
}
}}
>
{this.renderSwitch()}
<div className="label">{this.props.label}</div>
</div>
);
} else {
return this.renderSwitch();
}
}
}
@@ -1,129 +0,0 @@
/* eslint-disable react/prop-types */
import React, { Component } from 'react';
import MenusManager from '@components/menus/menus-manager.jsx';
import ColorPicker from 'components/color-picker/color-picker.jsx';
import Input from 'components/inputs/input.jsx';
import './inputs.scss';
export default class InputWithColor extends Component {
constructor() {
super();
}
outsideMenuListener() {
this.closeColorPicker();
}
componentWillUnmount() {
document.removeEventListener('click', this.outsideClickListener);
}
componentDidMount() {
if (this.props.focusOnDidMount && this.input) {
this.input.focus();
}
this.outsideClickListener = event => {
if (
this.colorPickerIsOpen &&
this.colorpicker_dom &&
!this.colorpicker_dom.contains(event.target) &&
document.contains(event.target)
) {
this.outsideMenuListener();
}
};
this.outsideClickListener = this.outsideClickListener.bind(this);
document.addEventListener('click', this.outsideClickListener);
}
closeColorPicker() {
if (!this.colorPickerIsOpen) {
return;
}
if (this.props.menu_level !== undefined) {
MenusManager.closeSubMenu(this.props.menu_level);
} else {
MenusManager.closeMenu();
}
this.colorPickerIsOpen = false;
}
openColorPicker() {
if (this.colorPickerIsOpen) {
return;
}
var menu = [
{
type: 'react-element',
reactElement: () => {
return (
<ColorPicker
refDom={node => (this.colorpicker_dom = node)}
value={this.props.value[0]}
onChange={color => this.selectColor(color)}
/>
);
},
},
];
var elementRect = window.getBoundingClientRect(this.color_dom);
elementRect.x = elementRect.x || elementRect.left;
elementRect.y = elementRect.y || elementRect.top;
if (this.props.menu_level !== undefined) {
MenusManager.openSubMenu(menu, elementRect, this.props.menu_level, 'bottom');
} else {
MenusManager.openMenu(menu, elementRect, 'bottom');
}
setTimeout(() => {
this.colorPickerIsOpen = true;
}, 200);
}
selectColor(color) {
this.closeColorPicker();
var value = [color, this.props.value[1]];
this.onChange(value);
}
onChange(value) {
if (this.props.onChange) {
this.props.onChange(value);
}
}
render() {
if (!this.props.value[0]) {
this.onChange([
ColorPicker.colors[parseInt(Math.random() * ColorPicker.colors.length)],
this.props.value[1],
]);
}
return (
<div className={'input_with_color ' + this.props.className}>
<div
className="color"
ref={node => (this.color_dom = node)}
onClick={() => {
this.openColorPicker();
}}
>
<div className="acolor" style={{ backgroundColor: this.props.value[0] }} />
</div>
<div className="right_input">
<Input
className="full_width medium"
refInput={obj => (this.input = obj)}
type="text"
placeholder={this.props.placeholder}
value={this.props.value[1]}
onKeyDown={e => {
if (e.keyCode == 13 && this.props.onEnter) {
this.props.onEnter();
}
}}
onChange={evt => {
if (this.onChange) this.onChange([this.props.value[0], evt.target.value]);
}}
/>
</div>
</div>
);
}
}
@@ -1,22 +0,0 @@
/* eslint-disable react/prop-types */
import React, { Component } from 'react';
import PlusIcon from '@material-ui/icons/AddOutlined';
export default class Rounded extends Component {
constructor() {
super();
}
render() {
return (
<div
style={this.props.style}
className={'rounded-btn ' + this.props.className}
onClick={this.props.onClick}
>
{this.props.text ? this.props.text + ' ' : ''}
<PlusIcon className="m-icon-small" />
</div>
);
}
}
@@ -1,100 +0,0 @@
import React, { Component } from 'react';
import './interactive-login-background.scss';
export default class InteractiveLoginBackground extends React.Component {
constructor(props) {
super();
this.lFollowX = 0;
this.lFollowY = 0;
this.x = 0;
this.y = 0;
this.friction = 1 / 30;
this.objects = [];
}
addObject() {
var div = document.createElement('div');
var size = Math.pow(0.1 + Math.random(), 2) * 10;
var left = Math.random() * 100 + 'vw';
div.style.width = size + 'px';
div.style.height = size + 'px';
var duration = 30 + Math.random() * 15;
var time_class = 'a';
if (duration > 40) {
time_class = 'b';
} else if (duration >= 35) {
time_class = 'c';
}
div.style.animationDelay = '-' + Math.random() * 45 + 's';
div.style.animationDuration = duration + 's';
div.style.left = left;
div.classList.add('animated_shape');
if (Math.random() > 0.5) {
div.classList.add('circle');
}
div.classList.add('speed-' + time_class);
this.background.appendChild(div);
this.objects.push(div);
}
mousemove(evt) {
this.lFollowX = evt.clientX / window.innerWidth;
this.lFollowY = evt.clientY / window.innerHeight;
}
moveBackground() {
if (!this.mounted) {
return;
}
this.x += (this.lFollowX - this.x) * this.friction;
this.y += (this.lFollowY - this.y) * this.friction;
this.objects.forEach(div => {
var fa, fb;
if (div.classList.contains('speed-a')) {
fa = 50;
fb = 15;
}
if (div.classList.contains('speed-b')) {
fa = 40;
fb = 10;
}
if (div.classList.contains('speed-c')) {
fa = 30;
fb = 5;
}
div.style.marginLeft = (this.x - 0.5) * fa;
div.style.marginTop = (this.y - 0.5) * fb;
});
window.requestAnimationFrame(this.moveBackground);
}
componentDidMount() {
for (var i = 0; i < 50; i++) {
this.addObject();
}
this.mousemove = this.mousemove.bind(this);
this.moveBackground = this.moveBackground.bind(this);
this.mounted = true;
this.moveBackground();
document.addEventListener('mousemove', this.mousemove);
}
componentWillUnmount() {
this.mounted = false;
document.removeEventListener('mousemove', this.mousemove);
}
render() {
return <div ref={node => (this.background = node)} className="animated_background" />;
}
}
@@ -1,42 +0,0 @@
.animated_background {
width: 100%;
height: 60vh;
position: relative;
background: var(--primary);
.animated_shape {
background: #fff;
top: calc(100% + 50px);
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-name: animated_background_shape_animation;
position: absolute;
border-radius: var(--border-radius-base);
}
.animated_shape.circle {
border-radius: 100%;
animation-name: animated_background_shape_animation_circle;
}
}
@keyframes animated_background_shape_animation {
0% {
transform: translateY(0);
opacity: 0.7;
}
100% {
transform: translateY(-100vh) rotate(600deg);
opacity: 0;
}
}
@keyframes animated_background_shape_animation_circle {
0% {
transform: translateY(0);
opacity: 0.7;
}
100% {
transform: translateY(-100vh);
opacity: 0;
}
}
@@ -1,21 +0,0 @@
.locked-history-banner {
.title-container {
display: flex;
align-items: center;
height: 24px;
margin: 16px 0 8px 0px;
.title {
line-height: 16px;
margin: 0;
margin-left: 8px;
font-size: 16px;
}
}
.description {
height: 30px;
text-align: center;
font-size: 12px;
}
}
@@ -1,46 +0,0 @@
import React from 'react';
import { Typography, Button } from 'antd';
import Banner from '@components/banner/banner';
import Emojione from '@components/emojione/emojione';
import Languages from '@features/global/services/languages-service';
import './locked-history-banner.scss';
import consoleService from '@features/console/services/console-service';
import useRouterCompany from '@features/router/hooks/use-router-company';
const { Title, Text } = Typography;
const LockedHistoryBanner = (): JSX.Element => {
const companyId = useRouterCompany();
const onClickBtn = () =>
window.open(consoleService.getCompanySubscriptionUrl(companyId), 'blank');
return (
<Banner
type="ghost"
height={135}
className="locked-history-banner"
contentColumnStyle={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
height: '100%',
width: '380px',
}}
>
<div className="title-container">
<Emojione type=":rocket:" s64 />
<Title level={5} className="title">
{Languages.t('components.locked_features.locked_history_banner.title')}
</Title>
</div>
<Text type="secondary" className="description">
{Languages.t('components.locked_features.locked_history_banner.description')}
</Text>
<Button type="primary" size="middle" onClick={onClickBtn} style={{ margin: '16px 0 16px 0' }}>
{Languages.t('components.locked_features.locked_history_banner.button')}
</Button>
</Banner>
);
};
export default LockedHistoryBanner;
@@ -1,72 +0,0 @@
import React from 'react';
import ObjectModal from '@components/object-modal/object-modal';
import { Button, Row, Typography } from 'antd';
import ModalManager from '@components/modal/modal-manager';
import Languages from '@features/global/services/languages-service';
import consoleService from '@features/console/services/console-service';
import useRouterCompany from '@features/router/hooks/use-router-company';
const { Title, Text } = Typography;
export default () => {
const companyId = useRouterCompany();
return (
<ObjectModal
titleCenter
titleLevel={2}
title={Languages.t('components.locked_features.locked_workspace_popup.title')}
titleTypographyStyle={{ textAlign: 'center', marginBottom: 32 }}
style={{ padding: 32 }}
contentStyle={{ display: 'flex', flexDirection: 'column', justifyContent: 'center' }}
footer={
<div
style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginTop: 32 }}
>
<Button
type="primary"
size="large"
style={{ marginTop: 8 }}
onClick={() =>
window.open(consoleService.getCompanySubscriptionUrl(companyId), 'blank')
}
>
{Languages.t('components.locked_features.locked_guests_popup.learn_more_button')}
</Button>
<Text style={{ margin: '16px 0 ' }} strong>
{Languages.t('components.locked_features.locked_guests_popup.or')}
</Text>
<Button
type="ghost"
style={{ height: 36, width: 163 }}
onClick={() => ModalManager.closeAll()}
>
{Languages.t('components.locked_features.locked_guests_popup.skip_for_now_button')}
</Button>
</div>
}
hideFooterDivider
footerAlign="center"
footerStyle={{ marginBottom: 16 }}
>
<Row justify="center" align="middle" className="bottom-margin">
<Title
level={3}
children={Languages.t('components.locked_features.locked_workspace_popup.subtitle')}
style={{
textAlign: 'center',
margin: 0,
}}
/>
</Row>
<Row justify="center">
<Text
style={{
textAlign: 'center',
width: '404px',
}}
children={Languages.t('components.locked_features.locked_workspace_popup.text')}
/>
</Row>
</ObjectModal>
);
};
@@ -1,118 +0,0 @@
import React, { Component } from 'react';
import Icon from '@components/icon/icon.jsx';
import PerfectScrollbar from 'react-perfect-scrollbar';
import Tabs from 'components/tabs/tabs.jsx';
import './deprecated-object-modal.scss';
import { Divider } from 'antd';
export class ObjectModalTitle extends Component {
render() {
return (
<div className={'modal_title ' + this.props.className} style={this.props.style}>
{this.props.children}
</div>
);
}
}
//ObjectModalSeparator
export class ObjectModalSeparator extends Component {
render() {
return <div className="separator"></div>;
}
}
//ObjectModalSectionTitle
export class ObjectModalSectionTitle extends Component {
render() {
return (
<div
style={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: this.props.smallMargin ? '16px' : '',
}}
>
<b>{this.props.title || this.props.children}</b>
<div>{this.props.action}</div>
</div>
);
}
}
// ObjectModalFormTitle
export class ObjectModalFormTitle extends Component {
render() {
return (
<div className={'section_title ' + this.props.className} style={this.props.style}>
{this.props.icon && <Icon type={this.props.icon} className="m-icon-small" />}
<span>{this.props.name}</span>
</div>
);
}
}
export class ObjectModal extends Component {
constructor(props) {
super();
this.state = {};
}
render() {
return (
<div className={'object_modal ' + this.props.className}>
<div className="top_right_buttons">
{this.props.onEdit && (
<div className="square_button" onClick={this.props.onEdit}>
<Icon type="edit-alt" className="m-icon-small" />
</div>
)}
{this.props.onClose && (
<div className="square_button" onClick={this.props.onClose}>
<Icon type="times" className="m-icon-small" />
</div>
)}
</div>
<div className={!this.props.noCloseButton ? 'title' : ''}>{this.props.title}</div>
{this.props.tabs && (
<Tabs
tabs={this.props.tabs.map(item => {
return {
title: item.title || '',
render: (
<div className="body">
<PerfectScrollbar options={{ suppressScrollX: true }} component="div">
{item.render}
</PerfectScrollbar>
</div>
),
};
})}
/>
)}
{!this.props.tabs && (
<div className="body">
{!!this.props.noScrollBar && (
<div className="child-with-margin">{this.props.children}</div>
)}
{!this.props.noScrollBar && (
<PerfectScrollbar options={{ suppressScrollX: true }} component="div">
{this.props.children}
</PerfectScrollbar>
)}
</div>
)}
{this.props.footer && <div className="separator" style={{ marginTop: 0 }} />}
{this.props.footer && (
<div className="footer bottom-margin">
<Divider />
<div className="x-margin">{this.props.footer}</div>
</div>
)}
</div>
);
}
}
@@ -1,64 +0,0 @@
.object_modal {
position: relative;
display: flex;
flex-direction: column;
margin-bottom: 24px;
& > .title {
padding-right: 56px;
margin: 16px 0 11px 16px;
}
& > .top_right_buttons {
position: absolute;
top: 16px;
right: 16px;
left: 16px;
text-align: right;
.square_button {
vertical-align: top;
display: inline-block;
width: 24px;
height: 24px;
line-height: 24px;
border-radius: var(--border-radius-base);
margin-left: 8px;
background: var(--grey-background);
cursor: pointer;
&:hover {
background: var(--primary-background);
}
}
}
& > .body {
margin: 0 0;
.scrollbar-container,
.child-with-margin {
padding: 16px;
max-height: calc(80vh - 200px);
}
}
.modal_title {
font-size: 24px;
color: var(--black);
}
}
.section_title {
color: var(--grey-dark);
font-size: 14px;
font-weight: 500;
margin-bottom: 8px;
margin-top: 24px;
i {
margin-right: 4px;
&:before {
margin-left: 0px;
}
}
}
@@ -1,199 +0,0 @@
/* eslint-disable react/no-direct-mutation-state */
import React, { Component } from 'react';
import Button from 'components/buttons/button.jsx';
import Input from 'components/inputs/input.jsx';
import Icon from '@components/icon/icon.jsx';
import Select from 'components/select/select.jsx';
import './reminder-selector.scss';
import Languages from '@features/global/services/languages-service';
export default class ReminderSelector extends React.Component {
constructor(props) {
super(props);
this.state = {
reminders: [],
};
this.old_value = JSON.stringify(props.reminders || []);
}
componentDidMount() {
this.updateFromProps(this.props);
}
shouldComponentUpdate(nextProps, nextState) {
if (this.old_value != JSON.stringify(nextProps.reminders)) {
this.old_value = JSON.stringify(nextProps.reminders);
this.updateFromProps(nextProps);
}
return true;
}
remove(i) {
delete this.state.reminders[i];
this.update();
}
add() {
this.state.reminders.push({
mode: 'push',
delay_unit: 'minutes',
delay_value: '30',
});
this.update();
}
update() {
var ret = [];
this.state.reminders.forEach(item => {
if (item.delay_unit == 'minutes' && item.delay_value > 59) {
item.delay_value = 30;
}
if (item.delay_unit == 'hours' && item.delay_value > 23) {
item.delay_value = 1;
}
if (item.delay_unit == 'days' && item.delay_value > 13) {
item.delay_value = 1;
}
if (item.delay_unit == 'weeks' && item.delay_value < 2) {
item.delay_value = 2;
}
ret.push({
mode: item.mode,
delay:
parseInt(item.delay_value) *
60 *
(item.delay_unit == 'hours' ? 60 : 1) *
(item.delay_unit == 'days' ? 60 * 24 : 1) *
(item.delay_unit == 'weeks' ? 60 * 24 * 7 : 1),
});
});
if (this.props.onChange) {
this.props.onChange(ret);
}
this.setState({});
}
updateFromProps(nextProps) {
var props = nextProps || this.props;
var reminders = [];
(props.reminders || []).forEach(item => {
var delay_value = parseInt(item.delay / 60);
var delay_unit = 'minutes';
if (item.delay > 59 * 60) {
delay_value = parseInt(item.delay / (60 * 60));
delay_unit = 'hours';
}
if (item.delay > 23 * 60 * 60) {
delay_value = parseInt(item.delay / (60 * 60 * 24));
delay_unit = 'days';
}
if (item.delay > 13 * 24 * 60 * 60) {
delay_value = parseInt(item.delay / (60 * 60 * 24 * 7));
delay_unit = 'weeks';
}
reminders.push({
mode: item.mode,
delay_value: delay_value,
delay_unit: delay_unit,
});
});
this.setState({ reminders: reminders });
}
render() {
return (
<div className="reminderSelector">
{this.state.reminders.map((reminder, i) => {
return (
<div className="bottom-margin" key={`reminder-${i}`}>
<Select
className="small small-right-margin"
value={reminder['mode'] || 'push'}
style={{ width: 'auto' }}
onChange={value => {
this.state.reminders[i].mode = value;
this.update();
}}
options={[
{
text: Languages.t('components.reminder.notification', [], 'Notification'),
value: 'push',
},
{
text: Languages.t('components.reminder.by_email', [], 'E-Mail'),
value: 'mail',
},
]}
/>
<Input
className="small small-right-margin"
type="number"
min="0"
max="60"
step="1"
value={reminder['delay_value'] || '0'}
onChange={evt => {
this.state.reminders[i].delay_value = evt.target.value;
if (!evt.target.value) {
return;
}
this.update();
}}
style={{ width: 60 }}
/>
<Select
className="small small-right-margin"
value={reminder['delay_unit'] || 'minutes'}
style={{ width: 'auto', marginLeft: 10 }}
onChange={value => {
this.state.reminders[i].delay_unit = value;
this.update();
}}
options={[
{
text: Languages.t('components.reminder.minutes_bef', [], 'minutes avant'),
value: 'minutes',
},
{
text: Languages.t('components.reminder.hours_bef', [], 'heures avant'),
value: 'hours',
},
{
text: Languages.t('components.reminder.days_bef', [], 'jours avant'),
value: 'days',
},
{
text: Languages.t('components.reminder.weeks_bef', [], 'semaines avant'),
value: 'weeks',
},
]}
/>
<Icon
type="trash"
className="remove_icon"
style={{ verticalAlign: 'middle' }}
onClick={() => this.remove(i)}
/>
</div>
);
})}
<Button small className="button secondary-text" onClick={() => this.add()}>
<Icon type="plus" className="m-icon-small" />{' '}
{Languages.t('scenes.apps.calendar.modals.reminder_add', [], 'Ajouter un rappel')}
</Button>
</div>
);
}
}
@@ -1,8 +0,0 @@
.reminderSelector {
.remove_icon {
cursor: pointer;
&:hover {
color: var(--red);
}
}
}
@@ -1,69 +0,0 @@
/* eslint-disable react/jsx-key */
import React, { Component } from 'react';
import Languages from '@features/global/services/languages-service';
import PerfectScrollbar from 'react-perfect-scrollbar';
import './tabs.scss';
export default class Tabs extends Component {
constructor(props) {
super(props);
this.state = {
i18n: Languages,
tab: props.selected,
};
Languages.addListener(this);
}
componentWillUnmount() {
Languages.removeListener(this);
}
select(i) {
this.setState({ tab: i });
this.props.onChange && this.props.onChange(i);
}
UNSAFE_componentWillUpdate(nextProps, nextState) {
if (nextProps.selected && JSON.stringify(nextProps.selected) != this.oldSelected) {
nextState.tab = nextProps.selected;
this.oldSelected = JSON.stringify(nextProps.selected);
}
}
render() {
var selected = this.state.tab || Object.keys(this.props.tabs || {})[0];
if (!this.props.tabs[selected]) {
selected = Object.keys(this.props.tabs || {})[0];
}
return (
<div className={'component_tabs ' + (this.props.fullBody ? 'full-body ' : '')}>
<PerfectScrollbar
options={{ suppressScrollY: true }}
component="div"
className="component_tabs_tabs"
>
{Object.keys(this.props.tabs || {}).map(i => {
var item = this.props.tabs[i];
return (
<div
style={item.titleStyle || {}}
className={
'component_tabs_tab ' +
(i == selected ? 'selected ' : '') +
(item.titleClassName || '') +
' '
}
onClick={() => this.select(i)}
>
{typeof item.title == 'function' ? item.title() : item.title}
</div>
);
})}
</PerfectScrollbar>
<div className="body ">
{typeof this.props.tabs[selected].render == 'function'
? this.props.tabs[selected].render()
: this.props.tabs[selected].render}
</div>
</div>
);
}
}
@@ -1,58 +0,0 @@
.component_tabs {
position: relative;
overflow: hidden;
&::before {
content: '';
position: relative;
right: 0px;
left: auto;
top: 0px;
height: 100%;
width: 50px;
z-index: 1;
pointer-events: none;
background: linear-gradient(to right, #ffffff00 0%, #ffffffff 100%);
}
& > .component_tabs_tabs {
border-bottom: 1px solid var(--grey-background);
padding: 0 16px;
white-space: nowrap;
max-width: 100%;
box-sizing: border-box;
.component_tabs_tab {
height: 40px;
box-sizing: border-box;
border-radius: 0;
display: inline-block;
padding: 8px 16px;
font-weight: 500;
color: var(--grey-dark);
font-size: 14px;
cursor: pointer;
&:hover {
background: transparent;
color: var(--black);
}
&.selected {
background: transparent;
border-bottom: 4px solid var(--primary);
color: var(--black);
}
}
}
& > .body {
padding: 16px;
}
&.full-body {
& > .body,
& > .component_tabs_tabs {
padding: 0px;
}
}
}
@@ -1,196 +0,0 @@
/* eslint-disable react/jsx-key */
/* eslint-disable react/no-direct-mutation-state */
import React, { Component } from 'react';
import Icon from '@components/icon/icon.jsx';
import Button from 'components/buttons/button.jsx';
import './tag-picker.scss';
import MenusManager from '@components/menus/menus-manager.jsx';
import TagSelector from './tag-selector.jsx';
import Workspaces from '@deprecated/workspaces/workspaces.jsx';
import Collections from '@deprecated/CollectionsV1/Collections/Collections.js';
import Languages from '@features/global/services/languages-service';
export default class TagPicker extends React.Component {
constructor(props) {
super();
this.props = props;
this.state = {
currentSelected: [],
inputValue: '',
currentList: [],
selected: [],
value: this.props.value || [],
list: props.data || [
{ id: 1, name: Languages.t('scenes.apps.tasks.task_status.todo', [], 'To do') },
{ id: 2, name: Languages.t('scenes.apps.tasks.task_status.current', [], 'Doing') },
{ id: 3, name: Languages.t('scenes.apps.tasks.task_status.done', [], 'Done') },
],
};
}
UNSAFE_componentWillUpdate(nextProps, nextState) {
if (JSON.stringify(nextProps.value) != JSON.stringify(this.props.value)) {
this.state.value = nextProps.value;
}
}
UNSAFE_componentWillMount() {
if (!this.props.data) {
Collections.get('tags').addListener(this);
Collections.get('tags').addSource(
{
http_base_url: 'globalsearch/tags',
http_options: {
workspace_id: Workspaces.currentWorkspaceId,
},
websockets: [{ uri: 'tags/' + Workspaces.currentWorkspaceId, options: { type: 'tags' } }],
},
Workspaces.currentWorkspaceId,
);
}
}
componentWillUnmount() {
if (!this.props.data) {
Collections.get('tags').removeListener(this);
}
}
addTags(evt) {
var menu = [
{
type: 'react-element',
reactElement: level => {
return (
<TagSelector
level={level}
data={
this.props.data
? this.props.data.map(a => {
if (typeof a == 'string') {
return { name: a, id: a, color: '#888' };
} else {
return a;
}
})
: false
}
canCreate={this.props.canCreate}
disabledTags={
this.state.value.map(item => {
return typeof item == 'string' ? item : item.id;
}) || []
}
onChange={value => {
value.forEach(tag => {
if (
this.state.value
.map(item => {
return typeof item == 'string' ? item : item.id;
})
.indexOf(tag.id || tag.name || tag) < 0
) {
this.state.value.push(tag.id || tag.name || tag);
}
});
if (!this.props.saveButton) this.props.onChange(this.state.value);
this.setState({});
if (this.props.menu_level !== undefined) {
MenusManager.closeSubMenu(this.props.menu_level);
} else {
MenusManager.closeMenu();
}
}}
/>
);
},
},
];
if (this.props.menu_level !== undefined) {
MenusManager.openSubMenu(
menu,
{ x: evt.clientX, y: evt.clientY },
this.props.menu_level,
'right',
);
} else {
MenusManager.openMenu(menu, { x: evt.clientX, y: evt.clientY }, 'right');
}
}
render() {
var value = this.state.value || [];
var tag_list = value.map(tag_id => {
var tag = false;
if (this.props.data) {
if (typeof tag_id == 'string') {
tag = { name: tag_id, id: tag_id, color: '#888' };
} else {
tag = tag_id;
tag.id = tag.id || tag.name;
tag.color = tag.color || '#888';
}
} else {
tag = Collections.get('tags').find(tag_id);
}
if (!tag) {
return '';
}
var name = tag.name;
return (
<div
className={
'tag ' + (this.props.inline ? 'inline-tag ' + (this.props.className || '') : '')
}
style={{ backgroundColor: tag.color }}
>
{name}{' '}
{!this.props.readOnly && (
<Icon
className="remove"
type="times"
onClick={() => {
this.state.value.splice(this.state.value.indexOf(tag.id), 1);
if (!this.props.saveButton) this.props.onChange(this.state.value);
this.setState({});
}}
/>
)}
</div>
);
});
if (this.props.inline) {
return tag_list;
}
return (
<div className={'tagPicker ' + (this.props.className || '')}>
{!this.props.readOnly && value.length == 0 && (
<div className="tag notag">{Languages.t('components.tagpicker.notag', [], 'No tag')}</div>
)}
{tag_list}
{!this.props.readOnly && (
<Button
className="small secondary-text"
onClick={evt => {
this.addTags(evt);
}}
>
<Icon type="plus" className="m-icon-small" /> {Languages.t('general.add', [], 'Add')}
</Button>
)}
{this.props.saveButton && (
<div className="full_width" style={{ textAlign: 'right' }}>
<Button
className="small primary"
value={Languages.t('general.save')}
onClick={() => {
this.props.onChange(this.state.value);
}}
/>
</div>
)}
</div>
);
}
}
@@ -1,104 +0,0 @@
.tagPicker .tag,
.inline-tag {
height: 22px;
border-radius: var(--border-radius-base);
background: var(--grey-dark);
color: #fff;
line-height: 22px;
vertical-align: top;
margin-bottom: 8px;
margin-right: 8px;
font-size: 12px;
font-weight: bold;
padding: 0 4px;
padding-left: 6px;
&.notag {
background: var(--grey-background);
color: var(--grey-dark);
}
.remove {
opacity: 0.5;
cursor: pointer;
&:hover {
opacity: 1;
}
}
.remove:before {
margin: 0px;
}
&.disabled {
opacity: 0.5;
}
}
.tagPicker {
.tag_selectable {
display: flex;
.tag_part {
flex: 1;
}
.edit {
}
}
.secondary-text {
height: 22px;
line-height: 22px;
}
&.disabled {
opacity: 0.5;
pointer-events: none;
}
.pickerInput {
padding-left: 5px;
&.readOnly {
padding-left: 0px;
}
}
.itemSelected {
display: inline-block;
.close {
font-size: 8px;
margin-left: 5px;
opacity: 0.4;
display: inline-block;
margin-right: -1px;
bottom: 0px;
position: relative;
}
.close:hover {
opacity: 0.8;
cursor: pointer;
}
}
.itemContoured {
padding: 1px 6px;
display: inline-block;
background-color: var(--primary);
box-sizing: border-box;
color: #fff;
border-radius: var(--border-radius-base);
margin: 5px 0px;
margin-right: 5px;
height: 18px;
line-height: 16px;
font-size: 12px;
}
.menu {
.itemContoured {
margin: 3px 0;
}
}
}
.inline-tag {
display: inline-block;
margin-bottom: 0px;
vertical-align: middle;
}
@@ -1,220 +0,0 @@
/* eslint-disable react/no-direct-mutation-state */
import React, { Component } from 'react';
import Picker from 'components/picker/picker.jsx';
import Button from 'components/buttons/button.jsx';
import Workspaces from '@deprecated/workspaces/workspaces.jsx';
import Collections from '@deprecated/CollectionsV1/Collections/Collections.js';
import Icon from '@components/icon/icon.jsx';
import ColorPicker from 'components/color-picker/color-picker.jsx';
import Strings from '@features/global/utils/strings';
import InputWithColor from 'components/inputs/input-with-color.jsx';
import AlertManager from '@features/global/services/alert-manager-service';
import Languages from '@features/global/services/languages-service';
import MenusManager from '@components/menus/menus-manager.jsx';
class TagEditor extends React.Component {
constructor(props) {
super();
this.props = props;
this.state = {
edited_tag_name: '',
edited_tag_color: '',
};
}
UNSAFE_componentWillMount() {
var tag = this.props.tag;
this.state.edited_tag_color = tag.color;
this.state.edited_tag_name = tag.name;
}
saveTag(tag) {
tag.color = this.state.edited_tag_color || tag.color;
tag.name = this.state.edited_tag_name || tag.name;
Collections.get('tags').save(tag, Workspaces.currentWorkspaceId);
MenusManager.closeSubMenu(this.props.level - 1);
}
render() {
var tag = this.props.tag;
return (
<div>
<InputWithColor
menu_level={this.props.level}
className="medium bottom-margin full_width"
focusOnDidMount
placeholder={Languages.t('components.tagpicker.tag_name', [], 'Tag name')}
value={[this.state.edited_tag_color, this.state.edited_tag_name]}
onEnter={() => {
this.saveTag(tag);
}}
onChange={value => {
this.setState({ edited_tag_color: value[0], edited_tag_name: value[1] });
}}
/>
<div style={{ textAlign: 'right' }}>
<Button
className="small"
onClick={() => {
this.saveTag(tag);
}}
value={Languages.t('general.save')}
/>
</div>
</div>
);
}
}
export default class TagSelector extends React.Component {
constructor(props) {
super();
this.props = props;
this.state = {
edited_tag_name: '',
edited_tag_color: '',
};
this.colors_random_list = ColorPicker.colors.map(a => a).sort(() => Math.random() - 0.5);
this.next_new_color = 0;
}
onUpdate(item) {}
onCreate(text, cb) {
var color = this.colors_random_list[this.next_new_color];
this.next_new_color = (this.next_new_color + 1) % this.colors_random_list.length;
var new_tag = Collections.get('tags').edit();
new_tag.name = text;
new_tag.color = color;
new_tag.workspace_id = Workspaces.currentWorkspaceId;
Collections.get('tags').save(new_tag, Workspaces.currentWorkspaceId, tag => {
cb(new_tag);
});
return new_tag;
}
onRemove(item, ev) {}
renderItemChoosen(item) {
return '';
}
editTag(evt, id) {
var tag = Collections.get('tags').find(id);
if (!tag) {
return;
}
var menu = [
{ type: 'title', text: Languages.t('general.edit') },
{
type: 'react-element',
reactElement: level => {
return <TagEditor tag={tag} parent={this} level={level} />;
},
},
{ type: 'separator' },
{
text: Languages.t('general.remove'),
className: 'error',
icon: 'trash',
onClick: ev => {
var tag = Collections.get('tags').find(id);
if (tag) {
AlertManager.confirm(() => {
MenusManager.closeSubMenu(this.props.level - 1);
Collections.get('tags').remove(tag, Workspaces.currentWorkspaceId);
});
}
return false;
},
},
];
MenusManager.openSubMenu(menu, { x: evt.clientX, y: evt.clientY }, this.props.level, 'right');
}
renderItem(item) {
var add_option = false;
if (typeof item == 'string') {
add_option = true;
item = { name: item, color: this.colors_random_list[this.next_new_color] };
}
var tag = (
<div
className={
'tag ' + (this.props.disabledTags.indexOf(item.id || item.name) >= 0 ? 'disabled' : '')
}
style={{ backgroundColor: item.color, margin: '5px 0' }}
>
{item.name}
</div>
);
if (add_option) {
return tag;
}
return (
<div className="tag_selectable">
<div className="tag_part">{tag}</div>
{!add_option && !this.props.data && (
<div
className="edit"
onClick={ev => {
ev.stopPropagation();
ev.preventDefault();
this.editTag(ev, item.id);
}}
>
<Icon type="ellipsis-h" />
</div>
)}
</div>
);
}
search(text, cb) {
var res = Collections.get('tags').findBy({ workspace_id: Workspaces.currentWorkspaceId });
if (this.props.data) {
res = this.props.data;
}
res = res
.filter(function (item) {
if (
Strings.removeAccents(item.name.toLowerCase().replace(/ +/, '')).indexOf(
Strings.removeAccents(text.toLowerCase().replace(/ +/, '')),
) !== -1
) {
return true;
}
return false;
})
.sort((a, b) => {
return this.props.disabledTags.indexOf(a.id) >= 0 ? -1 : 1;
});
cb(res);
}
render() {
return (
<Picker
className={'tagPicker ' + (this.props.disabled ? 'disabled ' : '')}
ref={picker => {
this.picker = picker;
}}
title={false}
search={(text, cb) => {
this.search(text, cb);
}}
renderItem={item => {
return this.renderItem(item);
}}
renderItemChoosen={item => {
return this.renderItemChoosen(item);
}}
renderItemSimply={item => {
return item.name;
}}
canCreate={this.props.canCreate !== false}
onCreate={(text, cb) => this.onCreate(text, cb)}
onSelect={item => this.onSelect(item)}
onChange={this.props.onChange}
value={this.props.value}
readOnly={this.props.readOnly}
inline={this.props.inline}
/>
);
}
}
@@ -1,255 +0,0 @@
/* eslint-disable react/jsx-key */
import React, { Component } from 'react';
import Workspaces from '@deprecated/workspaces/workspaces.jsx';
import Button from 'components/buttons/button.jsx';
import Languages from '@features/global/services/languages-service';
import Collections from '@deprecated/CollectionsV1/Collections/Collections.js';
import Emojione from 'components/emojione/emojione';
import Loader from 'components/loader/loader.jsx';
import TasksService from '@deprecated/Apps/Tasks/Tasks.js';
import LeftIcon from '@material-ui/icons/KeyboardArrowLeftOutlined';
import './task-picker.scss';
export default class TaskPicker extends Component {
/*
props : {
mode : "select_board" / "select_task"
}
*/
constructor(props) {
super(props);
this.tasks_collection_key = 'tasks_picker_' + Workspaces.currentWorkspaceId;
this.collection_key = [];
this.state = {
taskRepository: Collections.get('task'),
currentBoard: null,
currentList: null,
taskSelected: null,
boardRepository: Collections.get('boards'),
};
Languages.addListener(this);
Collections.get('boards').addListener(this);
Collections.get('lists').addListener(this);
Collections.get('tasks').addListener(this);
Collections.get('boards').addSource(
{
http_base_url: 'tasks/board',
http_options: {
workspace_id: Workspaces.currentWorkspaceId,
},
websockets: [
{ uri: 'boards/' + Workspaces.currentWorkspaceId, options: { type: 'board' } },
],
},
this.tasks_collection_key,
);
}
componentWillUnmount() {
Languages.removeListener(this);
Collections.get('boards').removeSource(this.tasks_collection_key);
Collections.get('lists').removeSource(this.tasks_collection_key);
Collections.get('tasks').removeSource(this.tasks_collection_key);
Collections.get('boards').removeListener();
Collections.get('lists').removeListener();
Collections.get('tasks').removeListener();
}
selectBoard(board) {
if (this.collection_key.indexOf(this.tasks_collection_key + '_' + board.id) < 0) {
this.collection_key.push(this.tasks_collection_key + '_' + board.id);
Collections.get('lists').addSource(
{
http_base_url: 'tasks/list',
http_options: {
board_id: board.id,
},
websockets: [{ uri: 'board_lists/' + board.id, options: { type: 'list' } }],
},
this.tasks_collection_key + '_' + board.id,
);
Collections.get('tasks').addSource(
{
http_base_url: 'tasks/task',
http_options: {
board_id: board.id,
},
websockets: [{ uri: 'board_tasks/' + board.id, options: { type: 'task' } }],
},
this.tasks_collection_key + '_' + board.id + '_tasks',
);
}
this.setState({ currentBoard: board });
}
selectList(list) {
this.setState({ currentList: list });
}
selectTask(task) {
this.setState({ taskSelected: task });
}
submit() {
if (this.props.mode === 'select_task' && this.state.taskSelected) {
if (this.props.onChoose) {
this.props.onChoose(this.state.taskSelected);
}
}
}
renderBoardPicker() {
var boards = Collections.get('boards').findBy({ workspace_id: Workspaces.currentWorkspaceId });
var loading =
!Collections.get('boards').did_load_first_time[this.tasks_collection_key] &&
boards.length === 0;
return (
<div className="boardPicker">
{loading && (
<div className="loading">
<Loader color="#CCC" className="app_loader" />
</div>
)}
{!loading &&
boards.map(board => {
return (
<div className="picker_item" onClick={() => this.selectBoard(board)}>
<div className="board_name_picker">
{board.emoji && (
<Emojione type={board.emoji} s16 className="board_emoji_picker" />
)}
<div className="text">{board.title}</div>
</div>
</div>
);
})}
</div>
);
}
renderListPicker() {
var loading =
!Collections.get('lists').did_load_first_time[
this.tasks_collection_key + '_' + this.state.currentBoard.id
];
var lists = Collections.get('lists').findBy({ board_id: this.state.currentBoard.id });
return (
<div className="">
{loading && (
<div className="loading">
<Loader color="#CCC" className="app_loader" />
</div>
)}
{!loading &&
lists
.sort(
(a, b) =>
TasksService.getElementIndex(a, 'lists_' + a.board_id) -
TasksService.getElementIndex(b, 'lists_' + b.board_id),
)
.map((item, index) => {
return (
<div
className="picker_item"
onClick={() => {
this.selectList(item);
}}
>
<div className="colorBloc" style={{ backgroundColor: item.color }} />
<div className="text">{item.title}</div>
</div>
);
})}
</div>
);
}
renderTaskPicker() {
var loading =
!Collections.get('tasks').did_load_first_time[
this.tasks_collection_key + '_' + this.state.currentBoard.id + '_tasks'
];
var tasks = Collections.get('tasks').findBy({
board_id: this.state.currentBoard.id,
list_id: this.state.currentList.id,
archived: false,
});
return (
<div className="item">
{loading && (
<div className="loading">
<Loader color="#CCC" className="app_loader" />
</div>
)}
{!loading &&
(tasks || [])
.sort(
(a, b) =>
TasksService.getElementIndex(a, 'tasks_' + a.list_id) -
TasksService.getElementIndex(b, 'tasks_' + b.list_id),
)
.map((item, index) => (
<div
className={
'picker_item ' +
(this.state.taskSelected &&
this.props.mode === 'select_task' &&
this.state.taskSelected.id === item.id
? 'is_selected'
: '')
}
onClick={() => {
this.selectTask(item);
}}
>
<div className="text">{item.title}</div>
</div>
))}
</div>
);
}
render() {
return (
<div className="taskPicker">
{!this.state.currentBoard && (
<div className="title">{Languages.t('scenes.apps.tasks.task')}</div>
)}
{this.state.currentBoard && !this.state.currentList && (
<div className="title">
<LeftIcon
className="m-icon-small getback"
onClick={() => {
Collections.get('lists').removeListener();
this.setState({ currentBoard: null });
}}
/>
{this.state.currentBoard.title}
</div>
)}
{this.state.currentBoard && this.state.currentList && (
<div className="title">
<LeftIcon
className="m-icon-small getback"
onClick={() => {
Collections.get('tasks').removeListener();
this.setState({ currentList: null });
}}
/>
{this.state.currentBoard.title} - {this.state.currentList.title}
</div>
)}
<div className="list">
{!this.state.currentBoard && this.renderBoardPicker()}
{this.state.currentBoard && !this.state.currentList && this.renderListPicker()}
{this.state.currentBoard && this.state.currentList && this.renderTaskPicker()}
</div>
<div className="menu-buttons">
{this.props.mode === 'select_task' &&
this.state.taskSelected &&
this.state.taskSelected.id && (
<Button
className="small"
value={Languages.t('scenes.app.taskpicker.select', [], 'Sélectionner')}
onClick={() => this.submit()}
/>
)}
</div>
</div>
);
}
}
@@ -1,76 +0,0 @@
.taskPicker {
position: relative;
.title {
background: #ffffff;
margin-bottom: 0px;
font-size: 16px;
color: #000;
line-height: 20px;
padding-bottom: 8px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.getback {
background: var(--grey-background);
border-radius: var(--border-radius-base);
width: 20px;
height: 20px;
vertical-align: top;
margin-right: 5px;
margin-left: 0px;
cursor: pointer;
}
}
.list {
height: 150px;
overflow: auto;
width: 100%;
.loading {
position: absolute;
margin: auto;
width: 50px;
height: 50px;
right: 0px;
bottom: 0px;
top: 0px;
left: 0px;
}
.picker_item {
display: flex;
flex-direction: row;
padding-left: 8px;
padding-right: 8px;
bottom: 0px;
color: var(--black);
height: 40px;
font-weight: 500;
width: 100%;
box-sizing: border-box;
border-top: 1px solid var(--grey-background);
font-size: 14px;
cursor: pointer;
.text {
display: inline-block;
line-height: 40px;
margin-left: 6px;
}
.board_emoji_picker {
vertical-align: top;
line-height: 40px;
}
.colorBloc {
height: 30px;
width: 4px;
margin-top: 5px;
}
}
.picker_item:hover {
background: var(--primary-background);
border-color: #fff;
}
.is_selected {
background: var(--primary);
color: #fff;
}
}
}
@@ -1,14 +0,0 @@
import React, { Component } from 'react';
import './elements.scss';
export default class UserConnectionDot extends React.Component {
render() {
if (this.props.connected && !this.props.notificationsDisabled) {
return <div className="connexion_dot green" />;
} else if (!this.props.connected && !this.props.notificationsDisabled) {
return <div className="connexion_dot grey" />;
} else {
return <div className="connexion_dot red" />;
}
}
}
@@ -1,87 +0,0 @@
import React, { Component } from 'react';
import Picker from 'components/picker/picker.jsx';
import Icon from '@components/icon/icon.jsx';
import './user-picker.scss';
import User from 'components/ui/user.jsx';
import UsersService from '@features/users/services/current-user-service';
import Languages from '@features/global/services/languages-service';
export default class UserPicker extends React.Component {
/*
hello
*/
constructor(props) {
super();
this.props = props;
this.state = {
currentSelected: [],
inputValue: '',
currentList: [],
selected: [],
};
}
componentWillUnmount() {}
onUpdate(item) {}
onRemove(item, ev) {}
renderItem(item, withEditor) {
return (
<div
className={
'itemContoured ' + (withEditor ? 'itemSelected ' : '') + (this.props.mini ? 'mini ' : '')
}
>
<User data={item} mini={this.props.mini} />
{!this.props.readOnly && withEditor && (
<div
className="close"
onClick={ev => {
this.picker.onRemove(item);
ev.stopPropagation();
ev.preventDefault();
}}
>
<Icon type="close" />
</div>
)}
</div>
);
}
search(text, cb) {
UsersService.search(text, { scope: this.props.scope || 'all' }, res => {
cb(res);
});
}
render() {
return (
<Picker
className="userPicker"
ref={picker => {
this.picker = picker;
}}
title={
this.props.title || Languages.t('components.drive.modify_uslist', [], 'Modify user list')
}
search={(text, cb) => {
this.search(text, cb);
}}
renderItem={item => {
return this.renderItem(item, false);
}}
renderItemChoosen={item => {
return this.renderItem(item, true);
}}
renderItemSimply={item => {
item = item || {};
return item.username;
}}
max={10}
onSelect={item => this.onSelect(item)}
onChange={this.props.onChange}
value={this.props.value}
readOnly={this.props.readOnly}
inline={this.props.inline}
/>
);
}
}
@@ -1,50 +0,0 @@
.userPicker {
.itemSelected {
display: inline-flex;
max-width: 100%;
.user_bloc {
flex: 1;
}
.close {
font-size: 8px;
margin-left: 5px;
opacity: 0.4;
display: inline-block;
margin-right: -1px;
bottom: 0px;
position: relative;
vertical-align: top;
margin-top: 5px;
}
.close:hover {
opacity: 0.8;
cursor: pointer;
}
}
.itemContoured {
display: inline-flex;
box-sizing: border-box;
color: #000;
margin: 5px;
height: 18px;
line-height: 16px;
font-size: 12px;
text-transform: capitalize;
border-radius: 9px;
padding-right: 6px;
&.mini {
padding-right: 0px;
margin-right: 0px;
}
}
.pickerInput:not(.readOnly) {
.itemContoured:hover {
background: #eee;
}
}
.menu .itemContoured {
margin: 3px;
}
}
@@ -2,7 +2,6 @@
import React, { Component } from 'react';
import UserService from '@features/users/services/current-user-service';
import NotificationParameters from '@deprecated/user/notification_parameters.js';
import ListenUsers from '@features/users/services/listen-users-service';
import UserOnlineStatus from '../online-user-status/online-user-status';
@@ -21,9 +20,6 @@ export default class User extends Component {
render() {
var user = this.props.user;
var notifications_disabled = false;
if (user && NotificationParameters.hasNotificationsDisabled(user.notifications_preferences)) {
notifications_disabled = true;
}
return (
<div
className={