aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/workspaces
diff options
context:
space:
mode:
Diffstat (limited to 'src/features/workspaces')
-rw-r--r--src/features/workspaces/actions.js8
-rw-r--r--src/features/workspaces/components/WorkspaceItem.js42
-rw-r--r--src/features/workspaces/components/WorkspacesDashboard.js63
-rw-r--r--src/features/workspaces/containers/EditWorkspaceScreen.js75
-rw-r--r--src/features/workspaces/containers/WorkspacesScreen.js37
-rw-r--r--src/features/workspaces/models/Workspace.js25
-rw-r--r--src/features/workspaces/store.js2
-rw-r--r--src/features/workspaces/styles/workspaces-table.scss53
8 files changed, 304 insertions, 1 deletions
diff --git a/src/features/workspaces/actions.js b/src/features/workspaces/actions.js
new file mode 100644
index 000000000..30866af96
--- /dev/null
+++ b/src/features/workspaces/actions.js
@@ -0,0 +1,8 @@
1import PropTypes from 'prop-types';
2import Workspace from './models/Workspace';
3
4export default {
5 edit: {
6 workspace: PropTypes.instanceOf(Workspace).isRequired,
7 },
8};
diff --git a/src/features/workspaces/components/WorkspaceItem.js b/src/features/workspaces/components/WorkspaceItem.js
new file mode 100644
index 000000000..b2c2a4830
--- /dev/null
+++ b/src/features/workspaces/components/WorkspaceItem.js
@@ -0,0 +1,42 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { intlShape } from 'react-intl';
4import { observer } from 'mobx-react';
5import classnames from 'classnames';
6import Workspace from '../models/Workspace';
7
8// const messages = defineMessages({});
9
10@observer
11class WorkspaceItem extends Component {
12 static propTypes = {
13 workspace: PropTypes.instanceOf(Workspace).isRequired,
14 onItemClick: PropTypes.func.isRequired,
15 };
16
17 static contextTypes = {
18 intl: intlShape,
19 };
20
21 render() {
22 const { workspace, onItemClick } = this.props;
23 // const { intl } = this.context;
24
25 return (
26 <tr
27 className={classnames({
28 'workspace-table__row': true,
29 })}
30 >
31 <td
32 className="workspace-table__column-name"
33 onClick={() => onItemClick(workspace)}
34 >
35 {workspace.name}
36 </td>
37 </tr>
38 );
39 }
40}
41
42export default WorkspaceItem;
diff --git a/src/features/workspaces/components/WorkspacesDashboard.js b/src/features/workspaces/components/WorkspacesDashboard.js
new file mode 100644
index 000000000..2a8b3a5ee
--- /dev/null
+++ b/src/features/workspaces/components/WorkspacesDashboard.js
@@ -0,0 +1,63 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl';
5
6import Loader from '../../../components/ui/Loader';
7import WorkspaceItem from './WorkspaceItem';
8
9const messages = defineMessages({
10 headline: {
11 id: 'settings.workspaces.headline',
12 defaultMessage: '!!!Your workspaces',
13 },
14 noServicesAdded: {
15 id: 'settings.workspaces.noWorkspacesAdded',
16 defaultMessage: '!!!You haven\'t added any workspaces yet.',
17 },
18});
19
20@observer
21class WorkspacesDashboard extends Component {
22 static propTypes = {
23 workspaces: MobxPropTypes.arrayOrObservableArray.isRequired,
24 isLoading: PropTypes.bool.isRequired,
25 onWorkspaceClick: PropTypes.func.isRequired,
26 };
27
28 static contextTypes = {
29 intl: intlShape,
30 };
31
32 render() {
33 const { workspaces, isLoading, onWorkspaceClick } = this.props;
34 const { intl } = this.context;
35
36 return (
37 <div className="settings__main">
38 <div className="settings__header">
39 <h1>{intl.formatMessage(messages.headline)}</h1>
40 </div>
41 <div className="settings__body">
42 {isLoading ? (
43 <Loader />
44 ) : (
45 <table className="workspace-table">
46 <tbody>
47 {workspaces.map(workspace => (
48 <WorkspaceItem
49 key={workspace.id}
50 workspace={workspace}
51 onItemClick={w => onWorkspaceClick(w)}
52 />
53 ))}
54 </tbody>
55 </table>
56 )}
57 </div>
58 </div>
59 );
60 }
61}
62
63export default WorkspacesDashboard;
diff --git a/src/features/workspaces/containers/EditWorkspaceScreen.js b/src/features/workspaces/containers/EditWorkspaceScreen.js
new file mode 100644
index 000000000..d8c52f586
--- /dev/null
+++ b/src/features/workspaces/containers/EditWorkspaceScreen.js
@@ -0,0 +1,75 @@
1import React, { Component } from 'react';
2import { inject, observer } from 'mobx-react';
3import { defineMessages, intlShape } from 'react-intl';
4import { Link } from 'react-router';
5import Form from '../../../lib/Form';
6import ErrorBoundary from '../../../components/util/ErrorBoundary';
7import { gaPage } from '../../../lib/analytics';
8import { state } from '../state';
9
10const messages = defineMessages({
11 name: {
12 id: 'settings.workspace.form.name',
13 defaultMessage: '!!!Name',
14 },
15 yourWorkspaces: {
16 id: 'settings.workspace.form.yourWorkspaces',
17 defaultMessage: '!!!Your workspaces',
18 },
19});
20
21@inject('stores', 'actions') @observer
22class EditWorkspaceScreen extends Component {
23 static contextTypes = {
24 intl: intlShape,
25 };
26
27 componentDidMount() {
28 gaPage('Settings/Workspace/Edit');
29 }
30
31 prepareForm(workspace) {
32 const { intl } = this.context;
33 const config = {
34 fields: {
35 name: {
36 label: intl.formatMessage(messages.name),
37 placeholder: intl.formatMessage(messages.name),
38 value: workspace.name,
39 },
40 },
41 };
42 return new Form(config);
43 }
44
45 render() {
46 const { intl } = this.context;
47 const { workspaceBeingEdited } = state;
48 if (!workspaceBeingEdited) return null;
49
50 // const form = this.prepareForm(workspaceBeingEdited);
51
52 return (
53 <ErrorBoundary>
54 <div className="settings__main">
55 <div className="settings__header">
56 <span className="settings__header-item">
57 <Link to="/settings/workspaces">
58 {intl.formatMessage(messages.yourWorkspaces)}
59 </Link>
60 </span>
61 <span className="separator" />
62 <span className="settings__header-item">
63 {workspaceBeingEdited.name}
64 </span>
65 </div>
66 <div className="settings__body">
67 test
68 </div>
69 </div>
70 </ErrorBoundary>
71 );
72 }
73}
74
75export default EditWorkspaceScreen;
diff --git a/src/features/workspaces/containers/WorkspacesScreen.js b/src/features/workspaces/containers/WorkspacesScreen.js
new file mode 100644
index 000000000..f129edec5
--- /dev/null
+++ b/src/features/workspaces/containers/WorkspacesScreen.js
@@ -0,0 +1,37 @@
1import React, { Component } from 'react';
2import { inject, observer } from 'mobx-react';
3import PropTypes from 'prop-types';
4import { gaPage } from '../../../lib/analytics';
5import { state } from '../state';
6import WorkspacesDashboard from '../components/WorkspacesDashboard';
7import ErrorBoundary from '../../../components/util/ErrorBoundary';
8
9@inject('actions') @observer
10class WorkspacesScreen extends Component {
11 static propTypes = {
12 actions: PropTypes.shape({
13 workspace: PropTypes.shape({
14 edit: PropTypes.func.isRequired,
15 }),
16 }).isRequired,
17 };
18
19 componentDidMount() {
20 gaPage('Settings/Workspaces Dashboard');
21 }
22
23 render() {
24 const { workspace } = this.props.actions;
25 return (
26 <ErrorBoundary>
27 <WorkspacesDashboard
28 workspaces={state.workspaces}
29 isLoading={state.isLoading}
30 onWorkspaceClick={w => workspace.edit({ workspace: w })}
31 />
32 </ErrorBoundary>
33 );
34 }
35}
36
37export default WorkspacesScreen;
diff --git a/src/features/workspaces/models/Workspace.js b/src/features/workspaces/models/Workspace.js
new file mode 100644
index 000000000..ede2710dc
--- /dev/null
+++ b/src/features/workspaces/models/Workspace.js
@@ -0,0 +1,25 @@
1import { observable } from 'mobx';
2
3export default class Workspace {
4 id = null;
5
6 @observable name = null;
7
8 @observable order = null;
9
10 @observable services = [];
11
12 @observable userId = null;
13
14 constructor(data) {
15 if (!data.id) {
16 throw Error('Workspace requires Id');
17 }
18
19 this.id = data.id;
20 this.name = data.name;
21 this.order = data.order;
22 this.services = data.services;
23 this.userId = data.userId;
24 }
25}
diff --git a/src/features/workspaces/store.js b/src/features/workspaces/store.js
index aab66708b..ea61cec31 100644
--- a/src/features/workspaces/store.js
+++ b/src/features/workspaces/store.js
@@ -1,7 +1,7 @@
1import { observable, reaction } from 'mobx'; 1import { observable, reaction } from 'mobx';
2import Store from '../../stores/lib/Store'; 2import Store from '../../stores/lib/Store';
3import CachedRequest from '../../stores/lib/CachedRequest'; 3import CachedRequest from '../../stores/lib/CachedRequest';
4import Workspace from '../../models/Workspace'; 4import Workspace from './models/Workspace';
5import { matchRoute } from '../../helpers/routing-helpers'; 5import { matchRoute } from '../../helpers/routing-helpers';
6 6
7const debug = require('debug')('Franz:feature:workspaces'); 7const debug = require('debug')('Franz:feature:workspaces');
diff --git a/src/features/workspaces/styles/workspaces-table.scss b/src/features/workspaces/styles/workspaces-table.scss
new file mode 100644
index 000000000..6d0e7b4f5
--- /dev/null
+++ b/src/features/workspaces/styles/workspaces-table.scss
@@ -0,0 +1,53 @@
1@import '../../../styles/config';
2
3.theme__dark .workspace-table {
4 .workspace-table__column-info .mdi { color: $dark-theme-gray-lightest; }
5
6 .workspace-table__row {
7 border-bottom: 1px solid $dark-theme-gray-darker;
8
9 &:hover { background: $dark-theme-gray-darker; }
10 &.workspace-table__row--disabled { color: $dark-theme-gray; }
11 }
12}
13
14.workspace-table {
15 width: 100%;
16
17 .workspace-table__toggle {
18 width: 60px;
19
20 .franz-form__field {
21 margin-bottom: 0;
22 }
23 }
24
25 .workspace-table__column-action {
26 width: 40px
27 }
28
29 .workspace-table__column-info {
30 width: 40px;
31
32 .mdi {
33 color: $theme-gray-light;
34 display: block;
35 font-size: 18px;
36 }
37 }
38
39 .workspace-table__row {
40 border-bottom: 1px solid $theme-gray-lightest;
41
42 &:hover {
43 cursor: initial;
44 background: $theme-gray-lightest;
45 }
46
47 &.workspace-table__row--disabled {
48 color: $theme-gray-light;
49 }
50 }
51
52 td { padding: 10px; }
53}