diff --git a/frontend/src/component/Entry/Project.js b/frontend/src/component/Entry/Project.js
new file mode 100644
index 0000000..16f4b97
--- /dev/null
+++ b/frontend/src/component/Entry/Project.js
@@ -0,0 +1,74 @@
+import PropTypes from 'prop-types';
+import React, { Component } from 'react';
+import { observer } from 'mobx-react';
+import { observable } from 'mobx';
+import { sortBy } from 'lodash';
+import { EntryItemProject } from '../EntryList';
+import { Entry } from 'store/Entry';
+import { ProjectStore } from 'store/Project';
+import InputSelect from '../InputSelect';
+
+function formatProjectToOption(project) {
+ return {
+ value: String(project.id),
+ label: project.name,
+ };
+}
+
+@observer
+export default class EntryProject extends Component {
+ static propTypes = {
+ entry: PropTypes.instanceOf(Entry).isRequired,
+ projectStore: PropTypes.instanceOf(ProjectStore).isRequired,
+ allowEdit: PropTypes.bool,
+ };
+
+ @observable editing = false;
+
+ handleBlur = () => {
+ this.editing = false;
+ this.props.entry.save();
+ };
+
+ handleClick = () => {
+ if (this.props.allowEdit) {
+ this.editing = true;
+ }
+ };
+
+ handleChange = (name, value) => {
+ this.props.entry.project = isNaN(value) ? null : parseInt(value);
+ };
+
+ render() {
+ const { entry, allowEdit } = this.props;
+ const project = entry.project
+ ? this.props.projectStore.get(entry.project)
+ : null;
+
+ let projectOptions = this.props.projectStore.map(formatProjectToOption);
+ projectOptions = sortBy(projectOptions, m => m.label.toLowerCase());
+
+ if (this.editing) {
+ return (
+
+
+
+ );
+ }
+ return (
+
+ {project ? project.name : No project}
+
+ );
+ }
+}
diff --git a/frontend/src/component/EntryList.js b/frontend/src/component/EntryList.js
index ed2aea7..f5af09a 100644
--- a/frontend/src/component/EntryList.js
+++ b/frontend/src/component/EntryList.js
@@ -20,12 +20,15 @@ export const EntryDay = styled.div`
export const EntryItemDescription = styled.div`
font-weight: bold;
+ margin-right: 20px;
flex: 3;
cursor: ${props => (props.allowEdit ? 'pointer' : 'default')};
`;
export const EntryItemProject = styled.div`
flex: 1;
+ margin-right: 20px;
+ cursor: ${props => (props.allowEdit ? 'pointer' : 'default')};
`;
export const EntryItemTime = styled.div`
diff --git a/frontend/src/component/InputSelect.js b/frontend/src/component/InputSelect.js
index b8e1e36..dd98f58 100644
--- a/frontend/src/component/InputSelect.js
+++ b/frontend/src/component/InputSelect.js
@@ -6,23 +6,23 @@ import styled from 'styled-components';
const StyledSelect = styled(Select)`
.Select-control {
- height: 48px;
+ height: ${props => (props.small ? '35' : '48')}px;
border: 0;
border-radius: 8px;
cursor: pointer;
}
.Select-input {
- height: 48px;
+ height: ${props => (props.small ? '35' : '48')}px;
}
.Select-input > input {
- line-height: 28px;
+ line-height: ${props => (props.small ? '14' : '28')}px;
}
.Select-placeholder,
.Select-control .Select-value {
- line-height: 48px !important;
+ line-height: ${props => (props.small ? '35' : '48')}px!important;
}
.Select-value-label {
@@ -52,6 +52,9 @@ export default class InputSelect extends Component {
options: MobxTypes.arrayOrObservableArray.isRequired,
value: PropTypes.string,
placeholder: PropTypes.string,
+ autoFocus: PropTypes.bool,
+ onBlur: PropTypes.func,
+ small: PropTypes.bool,
};
static defaultProps = {
@@ -77,6 +80,9 @@ export default class InputSelect extends Component {
options={this.props.options}
onChange={this.handleChange}
placeholder={this.props.placeholder}
+ autofocus={this.props.autoFocus}
+ onBlur={this.props.onBlur}
+ small={this.props.small}
/>
);
}
diff --git a/frontend/src/container/EntryOverviewItem.js b/frontend/src/container/EntryOverviewItem.js
index 9b3323e..200fb1e 100644
--- a/frontend/src/container/EntryOverviewItem.js
+++ b/frontend/src/container/EntryOverviewItem.js
@@ -13,6 +13,7 @@ import { UserStore } from 'store/User';
import { Entry } from 'store/Entry';
import IconDelete from 'image/icon-delete.svg';
import EntryDescription from 'component/Entry/Description';
+import EntryProject from 'component/Entry/Project';
function formatDiffMinutes(minutes) {
const hours = Math.floor(minutes / 60);
@@ -36,11 +37,9 @@ export default class EntryOverviewItem extends Component {
};
render() {
- const { entry, allowEdit } = this.props;
+ const { entry, allowEdit, projectStore } = this.props;
const diffMinutes = entry.differenceInMinutes;
- const project = entry.project
- ? this.props.projectStore.get(entry.project)
- : null;
+
let userColumn = null;
if (this.props.userStore) {
const user = entry.user
@@ -50,9 +49,11 @@ export default class EntryOverviewItem extends Component {
}
return (
-
- {project ? project.name : No project}
-
+
{entry.startedAt.format('H:mm')}
—