Skip to content

Commit 19820a5

Browse files
author
Cedomir Mijajlovic
committed
Merging production code v1.8.53
1 parent c16ef17 commit 19820a5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1812
-772
lines changed

clockify.pfx

-2.54 KB
Binary file not shown.

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<html>
22
<head>
3+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
34
<link rel="stylesheet" type="text/css" href="styles/main.css">
45
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap" rel="stylesheet">
5-
<script type="text/javascript" src="cordova.js"></script>
66
<script src="main.bundle.js" ></script>
77
<script src="vendors.main.bundle.js" ></script>
88
</head>

manifest.chrome.dev.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@
1616
"contentScripts/notification-background.js",
1717
"contentScripts/reminder-background.js",
1818
"contentScripts/pomodoro-background.js",
19-
"contentScripts/workspace-httpRequests-background.js",
2019
"contentScripts/project-httpRequests-background.js"
2120
]
2221
},
23-
"version": "1.8.44",
22+
"version": "1.8.53",
2423
"browser_action": {
2524
"default_popup": "index.html",
2625
"default_title": "Clockify"

manifest.firefox.dev.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
"contentScripts/notification-background.js",
1717
"contentScripts/reminder-background.js",
1818
"contentScripts/pomodoro-background.js",
19-
"contentScripts/workspace-httpRequests-background.js",
2019
"contentScripts/project-httpRequests-background.js"
2120
]
2221
},
@@ -26,7 +25,7 @@
2625
"strict_min_version": "57.0a1"
2726
}
2827
},
29-
"version": "1.8.44",
28+
"version": "1.8.53",
3029
"browser_action": {
3130
"default_popup": "index.html",
3231
"default_title": "Clockify"

package.json

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "Clockify",
3-
"version": "1.8.44",
4-
"description": "Clockify App 100% Free",
3+
"version": "1.8.53",
4+
"description": "Clockify App 100% Free Time Tracker",
55
"main": "main.js",
66
"productName": "Clockify",
77
"homepage": "https://clockify.me/",
@@ -31,8 +31,6 @@
3131
"react-datepicker": "^1.8.0",
3232
"react-dom": "^16.5.2",
3333
"react-http-request": "^2.0.0",
34-
"react-mobile-datepicker": "^3.0.12",
35-
"react-pullable": "^1.0.3",
3634
"url-parse": "^1.4.3"
3735
},
3836
"devDependencies": {

src/application.js

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ export class Application {
1717
}
1818

1919
afterLoad() {
20-
this.setWebSocketParamsToStorage();
2120
this.setBaseUrl();
2221
this.setHomeUrl();
2322
switch (this.appType) {
@@ -35,25 +34,19 @@ export class Application {
3534
}
3635
}
3736

38-
setWebSocketParamsToStorage() {
39-
localStorageService.set(
40-
"webSocketEndpoint",
41-
environment.webSocket.endpoint,
42-
getLocalStorageEnums().PERMANENT_PREFIX);
43-
localStorageService.set(
44-
"webSocketClientId",
45-
environment.webSocket.clientId,
46-
getLocalStorageEnums().PERMANENT_PREFIX);
47-
}
48-
4937
setBaseUrl() {
5038
const baseUrlFromStorage = settingsService.getBaseUrl();
5139
if (!baseUrlFromStorage) {
5240
settingsService.setBaseUrl(environment.endpoint);
5341
settingsService.setSelfHosted(false);
5442
} else {
55-
const selfHostedActive = baseUrlFromStorage !== environment.endpoint;
56-
settingsService.setSelfHosted(selfHostedActive);
43+
if (baseUrlFromStorage.includes('api.clockify.me/api')) {
44+
settingsService.setBaseUrl(environment.endpoint);
45+
settingsService.setSelfHosted(false);
46+
} else {
47+
const selfHostedActive = baseUrlFromStorage !== environment.endpoint;
48+
settingsService.setSelfHosted(selfHostedActive);
49+
}
5750
}
5851
}
5952

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
import * as React from 'react';
2+
import ProjectItem from './project-item.component';
3+
import {getDefaultProjectEnums} from "../enums/default-project.enum";
4+
import {ProjectService} from "../services/project-service";
5+
import {debounce} from "lodash";
6+
import {LocalStorageService} from "../services/localStorage-service";
7+
8+
const projectService = new ProjectService();
9+
const localStorageService = new LocalStorageService();
10+
const pageSize = 50;
11+
12+
class ProjectList extends React.Component {
13+
14+
constructor(props) {
15+
super(props);
16+
17+
this.state = {
18+
isOpen: false,
19+
selectedProject: {
20+
name: "Select default project",
21+
color: this.getColorForProject()
22+
},
23+
projectList:
24+
[{
25+
name: 'Last used project',
26+
color: '#999999',
27+
tasks: [],
28+
id: getDefaultProjectEnums().LAST_USED_PROJECT
29+
}],
30+
page: 1,
31+
ready: false,
32+
loadMore: true,
33+
title: '',
34+
filter: ''
35+
};
36+
this.filterProjects = debounce(this.filterProjects, 500);
37+
}
38+
39+
componentDidMount() {
40+
this.getProjects(this.state.page, pageSize);
41+
}
42+
43+
getProjects(page, pageSize) {
44+
if (page === 1) {
45+
this.setState({
46+
projectList:[{
47+
id: getDefaultProjectEnums().LAST_USED_PROJECT,
48+
name: 'Last used project',
49+
color: '#999999',
50+
tasks: []
51+
}]
52+
})
53+
}
54+
if (!JSON.parse(localStorage.getItem('offline'))) {
55+
projectService.getProjectsWithFilter(this.state.filter, page, pageSize)
56+
.then(response => {
57+
this.setState({
58+
projectList: this.state.projectList.concat(response.data),
59+
page: this.state.page + 1,
60+
ready: true
61+
}, () => {
62+
if(!this.state.isOpen) {
63+
this.mapSelectedProject();
64+
}
65+
});
66+
})
67+
.catch(() => {
68+
});
69+
} else {
70+
this.setState({
71+
ready: true
72+
})
73+
}
74+
}
75+
76+
mapSelectedProject() {
77+
const selectedProject = this.props.selectedProject === 'lastUsedProject' ?
78+
{
79+
name: 'Last used project',
80+
color: '#999999',
81+
tasks: [],
82+
id: getDefaultProjectEnums().LAST_USED_PROJECT
83+
} :
84+
this.state.projectList.filter(p => p.id === this.props.selectedProject)[0];
85+
86+
if (this.props.selectedProject && selectedProject) {
87+
this.setState({
88+
selectedProject: selectedProject
89+
}, () => {
90+
this.setState({
91+
title: this.createTitle()
92+
});
93+
})
94+
} else {
95+
if (this.props.selectedProject) {
96+
const projectIds = [];
97+
projectIds.push(this.props.selectedProject);
98+
projectService.getProjectsByIds(projectIds).then(response => {
99+
if (response.data.length > 0 && !response.data[0].archived) {
100+
this.setState({
101+
selectedProject: response.data[0]
102+
}, () => {
103+
this.setState({
104+
title: this.createTitle()
105+
});
106+
});
107+
}
108+
});
109+
} else {
110+
this.setState({
111+
selectedProject: {
112+
name: 'Select default project',
113+
color: this.getColorForProject()
114+
}
115+
}, () => {
116+
this.setState({
117+
title: this.createTitle()
118+
});
119+
});
120+
}
121+
}
122+
}
123+
124+
selectProject(project) {
125+
this.props.selectProject(project);
126+
127+
this.setState({
128+
selectedProject: project,
129+
isOpen: false
130+
}, () => this.setState({
131+
title: this.createTitle()
132+
})
133+
);
134+
}
135+
136+
openProjectDropdown() {
137+
if (!JSON.parse(localStorage.getItem('offline'))) {
138+
this.setState({
139+
isOpen: true,
140+
page: 1
141+
}, () => {
142+
document.getElementById('project-filter').focus();
143+
this.props.projectListOpened();
144+
});
145+
}
146+
}
147+
148+
closeProjectList() {
149+
document.getElementById('project-dropdown').scroll(0, 0);
150+
this.setState({
151+
isOpen: false,
152+
page: 1,
153+
filter: ''
154+
}, () => {
155+
document.getElementById('project-filter').value = "";
156+
this.getProjects(this.state.page, pageSize);
157+
});
158+
}
159+
160+
filterProjects() {
161+
this.setState({
162+
projectList: [{
163+
name: 'Last used project',
164+
color: '#999999',
165+
tasks: [],
166+
id: getDefaultProjectEnums().LAST_USED_PROJECT
167+
}],
168+
filter: document.getElementById('project-filter').value.toLowerCase(),
169+
page: 1
170+
}, () => {
171+
this.getProjects(this.state.page, pageSize);
172+
});
173+
}
174+
175+
loadMoreProjects() {
176+
this.getProjects(this.state.page, pageSize);
177+
}
178+
179+
createTitle() {
180+
let title = 'Select default project';
181+
if (this.state.selectedProject && this.state.selectedProject.id) {
182+
title = 'Project: ' + this.state.selectedProject.name;
183+
}
184+
185+
return title;
186+
}
187+
188+
clearProjectFilter() {
189+
this.setState({
190+
projectList:
191+
[{
192+
name: 'Last used project',
193+
color: '#999999',
194+
tasks: [],
195+
id: getDefaultProjectEnums().LAST_USED_PROJECT
196+
}],
197+
filter: '',
198+
page: 1
199+
}, () => {
200+
this.getProjects(this.state.page, pageSize);
201+
document.getElementById('project-filter').value = null
202+
});
203+
}
204+
205+
getColorForProject() {
206+
const userId = localStorageService.get('userId');
207+
const darkModeFromStorage = localStorageService.get('darkMode') ?
208+
JSON.parse(localStorageService.get('darkMode')) : [];
209+
210+
if (darkModeFromStorage.length > 0 &&
211+
darkModeFromStorage.filter(darkMode => darkMode.userId === userId && darkMode.enabled).length > 0
212+
) {
213+
return '#90A4AE';
214+
} else {
215+
return '#999999';
216+
}
217+
}
218+
219+
render() {
220+
if (!this.state.ready) {
221+
return null;
222+
} else {
223+
return (
224+
<div className="projects-list"
225+
title={this.state.title}>
226+
<div onClick={this.openProjectDropdown.bind(this)}
227+
className={JSON.parse(localStorage.getItem('offline')) ?
228+
"project-list-button-offline" : "project-list-button"}>
229+
<span style={{color: this.state.selectedProject ? this.state.selectedProject.color : "#999999"}}
230+
className="project-list-name">
231+
{this.state.selectedProject ? this.state.selectedProject.name : "Select default project"}
232+
</span>
233+
<span className="project-list-arrow">
234+
</span>
235+
</div>
236+
<div className={this.state.isOpen ? "project-list-open" : "disabled"}>
237+
<div onClick={this.closeProjectList.bind(this)} className="invisible"></div>
238+
<div className="project-list-dropdown"
239+
id="project-dropdown">
240+
<div className="project-list-dropdown--content">
241+
<div className="project-list-input">
242+
<div className="project-list-input--border">
243+
<input
244+
placeholder={"Filter projects"}
245+
className="project-list-filter"
246+
onChange={this.filterProjects.bind(this)}
247+
id="project-filter"
248+
/>
249+
<span className={!!this.state.filter ? "project-list-filter__clear" : "disabled"}
250+
onClick={this.clearProjectFilter.bind(this)}></span>
251+
</div>
252+
</div>
253+
{
254+
this.state.projectList.map(project => {
255+
return (
256+
<ProjectItem
257+
project={project}
258+
noTasks={true}
259+
selectProject={this.selectProject.bind(this)}
260+
workspaceSettings={this.props.workspaceSettings}
261+
isUserOwnerOrAdmin={this.props.isUserOwnerOrAdmin}
262+
/>
263+
)
264+
})
265+
}
266+
<div className={this.state.loadMore ? "project-list-load" : "disabled"}
267+
onClick={this.loadMoreProjects.bind(this)}>Load more
268+
</div>
269+
</div>
270+
</div>
271+
</div>
272+
</div>
273+
)
274+
}
275+
}
276+
}
277+
278+
export default ProjectList;

0 commit comments

Comments
 (0)