mirror of
https://github.com/FranP-code/Pomodoro-Timer-with-Clockify-integration.git
synced 2025-10-12 23:52:30 +00:00
Clockify tasks support added
This commit is contained in:
@@ -3,9 +3,13 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-svg-core": "^6.1.1",
|
||||||
|
"@fortawesome/free-solid-svg-icons": "^6.1.1",
|
||||||
|
"@fortawesome/react-fontawesome": "^0.1.18",
|
||||||
"@testing-library/jest-dom": "^5.14.1",
|
"@testing-library/jest-dom": "^5.14.1",
|
||||||
"@testing-library/react": "^11.2.7",
|
"@testing-library/react": "^11.2.7",
|
||||||
"@testing-library/user-event": "^12.8.3",
|
"@testing-library/user-event": "^12.8.3",
|
||||||
|
"@uiball/loaders": "^1.2.6",
|
||||||
"firebase": "^9.1.0",
|
"firebase": "^9.1.0",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-countdown": "^2.3.2",
|
"react-countdown": "^2.3.2",
|
||||||
|
|||||||
@@ -3,8 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Raleway:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Be+Vietnam+Pro:wght@400;700&family=Raleway:wght@400;700&family=Rambla:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Rambla:wght@400;700&display=swap" rel="stylesheet">
|
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="./img/favicon.ico" id="favicon" />
|
<link rel="icon" href="./img/favicon.ico" id="favicon" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
|||||||
@@ -1,27 +1,28 @@
|
|||||||
import './clockify-task-form.css'
|
import './clockify-task-form.css'
|
||||||
|
|
||||||
import React, { useState } from 'react';
|
import React, { useRef, useState } from 'react';
|
||||||
import { getAuth, onAuthStateChanged } from "firebase/auth";
|
import { getAuth, onAuthStateChanged } from "firebase/auth";
|
||||||
import { doc, getDoc, getFirestore } from "firebase/firestore";
|
import { doc, getDoc, getFirestore } from "firebase/firestore";
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
|
|
||||||
import { firebase } from '../../../Firebase/firebase';
|
import { firebase } from '../../../Firebase/firebase';
|
||||||
import Loading from "../../../components/Loading/Loading";
|
import Loading from "../../../components/Loading/Loading";
|
||||||
|
|
||||||
const ClockifyTaskForm = ({timerOn, setTimerOn, signedIn, apiKey, setApiKey, taskName, setTaskName, workspaceID, setWorkspaceID, projectID, setProjectID, darkMode}) => {
|
import {faCheck, faPlus} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { Ring } from '@uiball/loaders'
|
||||||
|
|
||||||
|
const ClockifyTaskForm = ({timerOn, setTimerOn, signedIn, apiKey, setApiKey, taskName, setTaskName, projectID, setProjectID, darkMode, taskID, setTaskID, clockifyData, changeClockifyData}) => {
|
||||||
|
|
||||||
const auth = getAuth()
|
const auth = getAuth()
|
||||||
|
|
||||||
const [userUID, setUserUID] = useState('')
|
const descriptionInput = useRef("")
|
||||||
|
|
||||||
const [workspaces, setWorkspaces] = useState([])
|
|
||||||
const [workspacesReady, setWorkspacesReady] = useState(false)
|
|
||||||
|
|
||||||
const [projects, setProjects] = useState([])
|
|
||||||
const [projectsDone, setProjectsDone] = useState(false)
|
|
||||||
|
|
||||||
const [loading, setLoading] = useState(true)
|
const [loading, setLoading] = useState(true)
|
||||||
|
|
||||||
async function getApiKey() {
|
let newTask = useRef("")
|
||||||
|
const [addingNewTask, setAddingNewTask] = useState(false)
|
||||||
|
|
||||||
|
async function getApiKey(userUID) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
@@ -39,25 +40,22 @@ const ClockifyTaskForm = ({timerOn, setTimerOn, signedIn, apiKey, setApiKey, tas
|
|||||||
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
|
||||||
if (signedIn) {
|
if (signedIn) {
|
||||||
|
|
||||||
onAuthStateChanged(auth, async (user) => {
|
onAuthStateChanged(auth, async (user) => {
|
||||||
|
|
||||||
if (user) {
|
if (user && user.uid) {
|
||||||
|
|
||||||
setUserUID(user.uid)
|
await getApiKey(user.uid)
|
||||||
|
setLoading(false)
|
||||||
if (user.uid) {
|
|
||||||
await getApiKey()
|
|
||||||
setLoading(false)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return (<></>)
|
return (<></>)
|
||||||
}
|
}
|
||||||
@@ -67,7 +65,7 @@ const ClockifyTaskForm = ({timerOn, setTimerOn, signedIn, apiKey, setApiKey, tas
|
|||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
}, [signedIn, getApiKey])
|
}, [signedIn])
|
||||||
|
|
||||||
async function makeRequestWorkspaces(apiClockify) {
|
async function makeRequestWorkspaces(apiClockify) {
|
||||||
try {
|
try {
|
||||||
@@ -86,7 +84,7 @@ const ClockifyTaskForm = ({timerOn, setTimerOn, signedIn, apiKey, setApiKey, tas
|
|||||||
return await data
|
return await data
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,20 +93,17 @@ const ClockifyTaskForm = ({timerOn, setTimerOn, signedIn, apiKey, setApiKey, tas
|
|||||||
const data = await makeRequestWorkspaces(key)
|
const data = await makeRequestWorkspaces(key)
|
||||||
|
|
||||||
if (data.code !== 1000) {
|
if (data.code !== 1000) {
|
||||||
let workspacesCopy = []
|
let workspaces = []
|
||||||
|
|
||||||
await data.forEach(workspace => {
|
await data.forEach(workspace => {
|
||||||
workspacesCopy.push(workspace)
|
workspaces.push(workspace)
|
||||||
});
|
});
|
||||||
|
|
||||||
setWorkspaces(workspacesCopy)
|
changeClockifyData({workspaces: workspaces})
|
||||||
|
|
||||||
setWorkspacesReady(true)
|
|
||||||
setLoading(false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function requestProjects(e) {
|
const getProjects = async (e) => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const request = {
|
const request = {
|
||||||
@@ -119,32 +114,70 @@ const ClockifyTaskForm = ({timerOn, setTimerOn, signedIn, apiKey, setApiKey, tas
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const response = await fetch(`https://api.clockify.me/api/v1/workspaces/${e}/projects`, request)
|
const response = await fetch(`https://api.clockify.me/api/v1/workspaces/${e}/projects`, request)
|
||||||
const data = response.json()
|
const data = await response.json()
|
||||||
|
|
||||||
|
console.log(data);
|
||||||
|
changeClockifyData({projects: data})
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const defineProjects = async (e) => {
|
async function getTasks(projectID) {
|
||||||
|
|
||||||
if (e === 0) {
|
|
||||||
setProjectsDone(false)
|
|
||||||
setProjects([])
|
|
||||||
|
|
||||||
|
if (projectID === "0") {
|
||||||
|
changeClockifyData({projectID: undefined})
|
||||||
|
changeClockifyData({tasks: undefined})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
setWorkspaceID(e)
|
|
||||||
|
|
||||||
const data = await requestProjects(e)
|
try {
|
||||||
setProjects(data)
|
const request = {
|
||||||
setProjectsDone(true)
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
'X-Api-Key': apiKey,
|
||||||
|
"content-type": "application/json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const response = await fetch(`https://api.clockify.me/api/v1/workspaces/${clockifyData.workspaceID}/projects/${projectID}/tasks`, request)
|
||||||
|
const data = await response.json()
|
||||||
|
|
||||||
|
changeClockifyData({tasks: data})
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectProject = (e) => {
|
async function addNewTask() {
|
||||||
|
|
||||||
setProjectID(e)
|
setAddingNewTask("loading")
|
||||||
|
|
||||||
|
try {
|
||||||
|
const url = `https://api.clockify.me/api/v1/workspaces/${clockifyData.workspaceID}/projects/${clockifyData.projectID}/tasks`
|
||||||
|
const request = {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({
|
||||||
|
name: newTask.current.value
|
||||||
|
}),
|
||||||
|
headers: {
|
||||||
|
'X-Api-Key': apiKey,
|
||||||
|
"content-type": "application/json",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await fetch(url, request)
|
||||||
|
|
||||||
|
newTask.current.value = ""
|
||||||
|
|
||||||
|
await getTasks(clockifyData.projectID)
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
setAddingNewTask(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -155,41 +188,107 @@ const ClockifyTaskForm = ({timerOn, setTimerOn, signedIn, apiKey, setApiKey, tas
|
|||||||
:
|
:
|
||||||
<div className={darkMode ? 'clockify-task-form-container dark-mode-container' : 'clockify-tasks-display-container'}>
|
<div className={darkMode ? 'clockify-task-form-container dark-mode-container' : 'clockify-tasks-display-container'}>
|
||||||
{
|
{
|
||||||
userUID ?
|
clockifyData.workspaces ?
|
||||||
<div className={`clockify-task-form ${timerOn || !workspacesReady ? "disabled" : ""}`}>
|
<div className={`clockify-task-form ${(timerOn || !clockifyData.workspaces) && "disabled"}`}>
|
||||||
<select onChange={(e) => {defineProjects(e.target.value)}} className='workspace-selector'>
|
|
||||||
|
<select
|
||||||
|
onChange={(e) => {
|
||||||
|
changeClockifyData({workspaceID: e.target.value})
|
||||||
|
getProjects(e.target.value)
|
||||||
|
}}
|
||||||
|
className='workspace-selector'
|
||||||
|
>
|
||||||
<option value="0">Select a Workspace</option>
|
<option value="0">Select a Workspace</option>
|
||||||
{
|
{
|
||||||
workspacesReady ?
|
clockifyData.workspaces &&
|
||||||
workspaces.map( (workspace) => {
|
clockifyData.workspaces.map((workspace) => {
|
||||||
return <option value={workspace.id} key={workspace.id}>{workspace.name}</option>
|
return <option value={workspace.id} key={workspace.id}>{workspace.name}</option>
|
||||||
})
|
})
|
||||||
: null
|
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
<select onChange={(e) => {selectProject(e.target.value)}} className={workspaceID !== 0 ? 'project-selector' : 'project-selector disabled'}>
|
|
||||||
|
<select
|
||||||
|
onChange={(e) => {
|
||||||
|
changeClockifyData({projectID: e.target.value})
|
||||||
|
getTasks(e.target.value)
|
||||||
|
}}
|
||||||
|
className={`project-selector ${(!clockifyData.workspaceID) && 'disabled'}`}
|
||||||
|
>
|
||||||
<option value="0">Select a Project</option>
|
<option value="0">Select a Project</option>
|
||||||
{
|
{
|
||||||
projectsDone && projects.length !== 0 ?
|
clockifyData.projects &&
|
||||||
projects.map((project) => (
|
clockifyData.projects.map((project) => (
|
||||||
!project.archived ?
|
!project.archived ?
|
||||||
<option value={project.id} key={project.id}>{project.name}</option>
|
<option value={project.id} key={project.id} style={{color: project.color}}>{project.name}</option>
|
||||||
: null
|
: null
|
||||||
))
|
))
|
||||||
: null
|
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select
|
||||||
|
onChange={(e) => {
|
||||||
|
if (e.target.value === "0") {
|
||||||
|
changeClockifyData({taskID: undefined})
|
||||||
|
} else {
|
||||||
|
changeClockifyData({taskID: e.target.value})
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className={`project-selector ${(!clockifyData.projectID || (clockifyData.tasks && clockifyData.tasks.length === 0)) && 'disabled'}`}
|
||||||
|
>
|
||||||
|
<option value="0">Select a Task</option>
|
||||||
|
{
|
||||||
|
clockifyData.tasks &&
|
||||||
|
clockifyData.tasks.map((task) => (
|
||||||
|
task.status !== "DONE" &&
|
||||||
|
<option value={task.id} key={task.id} >{task.name}</option>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
<button
|
||||||
|
className={`add-task ${!clockifyData.projectID && 'disabled'}`}
|
||||||
|
onClick={() => {
|
||||||
|
|
||||||
|
if (addingNewTask === "loading") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!addingNewTask) {
|
||||||
|
setAddingNewTask(true)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
addNewTask()
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
addingNewTask === false ?
|
||||||
|
<FontAwesomeIcon icon={faPlus} />
|
||||||
|
: addingNewTask === true ?
|
||||||
|
<FontAwesomeIcon icon={faCheck} />
|
||||||
|
: addingNewTask === "loading" &&
|
||||||
|
<Ring size={20} color="#fff" />
|
||||||
|
}
|
||||||
|
|
||||||
|
</button>
|
||||||
|
<>
|
||||||
|
{
|
||||||
|
addingNewTask &&
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
ref={newTask}
|
||||||
|
placeholder="Set new task name"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
onChange={(e) => {setTaskName(e.target.value)}}
|
ref={descriptionInput}
|
||||||
value={taskName}
|
onChange={(e) => changeClockifyData({description: e.target.value})}
|
||||||
placeholder="Add task description"
|
placeholder="Add task description"
|
||||||
className={projectID !== 0 ? null: 'disabled'}
|
className={!clockifyData.projectID && 'disabled'}
|
||||||
|
|
||||||
onKeyPress={event => {
|
onKeyPress={event => {
|
||||||
|
|
||||||
if (event.key === 'Enter') {
|
if (event.key === 'Enter') {
|
||||||
|
|
||||||
setTimerOn(true)
|
setTimerOn(true)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -4,32 +4,39 @@
|
|||||||
top: 60vh;
|
top: 60vh;
|
||||||
left: 2.5vw;
|
left: 2.5vw;
|
||||||
}
|
}
|
||||||
|
.clockify-task-form input::-moz-placeholder {
|
||||||
|
font-family: "Arial", sans-serif;
|
||||||
|
}
|
||||||
|
.clockify-task-form input:-ms-input-placeholder {
|
||||||
|
font-family: "Arial", sans-serif;
|
||||||
|
}
|
||||||
|
.clockify-task-form select, .clockify-task-form select option, .clockify-task-form input, .clockify-task-form input::placeholder {
|
||||||
|
font-family: "Arial", sans-serif;
|
||||||
|
}
|
||||||
.clockify-task-form.loading-container {
|
.clockify-task-form.loading-container {
|
||||||
width: 20vw;
|
width: 20vw;
|
||||||
height: auto;
|
height: auto;
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
.clockify-task-form.disabled {
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
cursor: initial;
|
|
||||||
pointer-events: none;
|
|
||||||
opacity: 30%;
|
|
||||||
}
|
|
||||||
.clockify-task-form .workspace-selector, .clockify-task-form .project-selector {
|
.clockify-task-form .workspace-selector, .clockify-task-form .project-selector {
|
||||||
width: 15vw;
|
width: 15vw;
|
||||||
height: 3vw;
|
height: 5vh;
|
||||||
}
|
}
|
||||||
.clockify-task-form .workspace-selector.disabled, .clockify-task-form .project-selector.disabled {
|
.clockify-task-form .add-task {
|
||||||
-webkit-user-select: none;
|
width: 3.5vh;
|
||||||
-moz-user-select: none;
|
height: 3.5vh;
|
||||||
-ms-user-select: none;
|
margin-left: 0.5vh;
|
||||||
user-select: none;
|
display: inline;
|
||||||
cursor: initial;
|
background-color: var(--main-text-color);
|
||||||
pointer-events: none;
|
border-radius: 100%;
|
||||||
opacity: 30%;
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.clockify-task-form .add-task:hover {
|
||||||
|
filter: brightness(90%);
|
||||||
|
}
|
||||||
|
.clockify-task-form .add-task:active {
|
||||||
|
filter: brightness(110%);
|
||||||
}
|
}
|
||||||
.clockify-task-form select {
|
.clockify-task-form select {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -44,14 +51,14 @@
|
|||||||
padding: 1px 2px;
|
padding: 1px 2px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
.clockify-task-form input[type=text].disabled {
|
.clockify-task-form .disabled {
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
-ms-user-select: none;
|
-ms-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
cursor: initial;
|
cursor: initial;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
opacity: 30%;
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 991.98px) {
|
@media (max-width: 991.98px) {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"sources":["clockify-task-form.scss","clockify-task-form.css"],"names":[],"mappings":"AAAA;EAEI,WAAA;EACA,kBAAA;EAEA,SAAA;EACA,WAAA;ACDJ;ADGI;EACI,WAAA;EACA,YAAA;EACA,gBAAA;ACDR;ADII;EACI,yBAAA;KAAA,sBAAA;MAAA,qBAAA;UAAA,iBAAA;EACA,eAAA;EACA,oBAAA;EACA,YAAA;ACFR;ADKI;EACI,WAAA;EACA,WAAA;ACHR;ADKQ;EACI,yBAAA;KAAA,sBAAA;MAAA,qBAAA;UAAA,iBAAA;EACA,eAAA;EACA,oBAAA;EACA,YAAA;ACHZ;ADOI;EACI,gBAAA;EACA,mBAAA;EACA,uBAAA;ACLR;ADQI;EACI,WAAA;EACA,WAAA;EAEA,eAAA;EAEA,aAAA;EACA,gBAAA;EAEA,sBAAA;ACTR;ADWQ;EACI,yBAAA;KAAA,sBAAA;MAAA,qBAAA;UAAA,iBAAA;EACA,eAAA;EACA,oBAAA;EACA,YAAA;ACTZ;;ADcA;EAEI;IACI,iBAAA;IACA,WAAA;IAEA,aAAA;IACA,6BAAA;IAEA,gBAAA;ECdN;EDgBM;IACI,UAAA;IACA,YAAA;ECdV;EDiBM;IACI,WAAA;IACA,WAAA;ECfV;AACF;ADoBA;EAEI;IACI,iBAAA;IACA,WAAA;IAEA,aAAA;IACA,sBAAA;IACA,mBAAA;ECpBN;EDsBM;IACI,UAAA;IACA,YAAA;ECpBV;EDuBM;IACI,UAAA;IACA,WAAA;IACA,eAAA;ECrBV;AACF","file":"clockify-task-form.css"}
|
{"version":3,"sources":["clockify-task-form.scss","clockify-task-form.css"],"names":[],"mappings":"AAAA;EAEI,WAAA;EACA,kBAAA;EAEA,SAAA;EACA,WAAA;ACDJ;ADGI;EACI,gCAAA;ACDR;ADAI;EACI,gCAAA;ACDR;ADAI;EACI,gCAAA;ACDR;ADII;EACI,WAAA;EACA,YAAA;EACA,gBAAA;ACFR;ADKI;EACI,WAAA;EACA,WAAA;ACHR;ADMI;EACI,YAAA;EACA,aAAA;EAEA,kBAAA;EAEA,eAAA;EAEA,wCAAA;EACA,mBAAA;EAEA,WAAA;EAEA,eAAA;ACTR;ADWQ;EACI,uBAAA;ACTZ;ADYQ;EACI,wBAAA;ACVZ;ADcI;EACI,gBAAA;EACA,mBAAA;EACA,uBAAA;ACZR;ADeI;EACI,WAAA;EACA,WAAA;EAEA,eAAA;EAEA,aAAA;EACA,gBAAA;EAEA,sBAAA;AChBR;ADmBI;EACI,yBAAA;KAAA,sBAAA;MAAA,qBAAA;UAAA,iBAAA;EACA,eAAA;EACA,oBAAA;EACA,YAAA;ACjBR;;ADqBA;EAEI;IACI,iBAAA;IACA,WAAA;IAEA,aAAA;IACA,6BAAA;IAEA,gBAAA;ECrBN;EDuBM;IACI,UAAA;IACA,YAAA;ECrBV;EDwBM;IACI,WAAA;IACA,WAAA;ECtBV;AACF;AD2BA;EAEI;IACI,iBAAA;IACA,WAAA;IAEA,aAAA;IACA,sBAAA;IACA,mBAAA;EC3BN;ED6BM;IACI,UAAA;IACA,YAAA;EC3BV;ED8BM;IACI,UAAA;IACA,WAAA;IACA,eAAA;EC5BV;AACF","file":"clockify-task-form.css"}
|
||||||
@@ -6,28 +6,42 @@
|
|||||||
top: 60vh;
|
top: 60vh;
|
||||||
left: 2.5vw;
|
left: 2.5vw;
|
||||||
|
|
||||||
|
select, select option, input, input::placeholder {
|
||||||
|
font-family: 'Arial', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
&.loading-container {
|
&.loading-container {
|
||||||
width: 20vw;
|
width: 20vw;
|
||||||
height: auto;
|
height: auto;
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.disabled {
|
|
||||||
user-select: none;
|
|
||||||
cursor: initial;
|
|
||||||
pointer-events: none;
|
|
||||||
opacity: 30%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.workspace-selector, .project-selector {
|
.workspace-selector, .project-selector {
|
||||||
width: 15vw;
|
width: 15vw;
|
||||||
height: 3vw;
|
height: 5vh;
|
||||||
|
}
|
||||||
|
|
||||||
&.disabled {
|
.add-task {
|
||||||
user-select: none;
|
width: 3.5vh;
|
||||||
cursor: initial;
|
height: 3.5vh;
|
||||||
pointer-events: none;
|
|
||||||
opacity: 30%;
|
margin-left: 0.5vh;
|
||||||
|
|
||||||
|
display: inline;
|
||||||
|
|
||||||
|
background-color: var(--main-text-color);
|
||||||
|
border-radius: 100%;
|
||||||
|
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
filter: brightness(90%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
filter: brightness(110%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,13 +61,13 @@
|
|||||||
padding: 1px 2px;
|
padding: 1px 2px;
|
||||||
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
&.disabled {
|
.disabled {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
cursor: initial;
|
cursor: initial;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
opacity: 30%;
|
opacity: 0.3;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,15 @@ const Main = ({signedIn, darkMode, setKonamiCodeActive, KonamiCodeActive, notifi
|
|||||||
|
|
||||||
const [timerOn, setTimerOn] = useState(false)
|
const [timerOn, setTimerOn] = useState(false)
|
||||||
const [apiKey, setApiKey] = useState('')
|
const [apiKey, setApiKey] = useState('')
|
||||||
const [taskName, setTaskName] = useState('')
|
|
||||||
|
|
||||||
const [workspaceID, setWorkspaceID] = useState(0)
|
const [clockifyData, setClockifyData] = useState({})
|
||||||
const [projectID, setProjectID] = useState(0)
|
|
||||||
|
function changeClockifyData(obj) {
|
||||||
|
setClockifyData(clockifyData => ({
|
||||||
|
...clockifyData,
|
||||||
|
...obj
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -24,16 +29,8 @@ const Main = ({signedIn, darkMode, setKonamiCodeActive, KonamiCodeActive, notifi
|
|||||||
apiKey={apiKey}
|
apiKey={apiKey}
|
||||||
setApiKey={setApiKey}
|
setApiKey={setApiKey}
|
||||||
|
|
||||||
taskName={taskName}
|
clockifyData={clockifyData}
|
||||||
setTaskName={setTaskName}
|
changeClockifyData={changeClockifyData}
|
||||||
|
|
||||||
workspaceID={workspaceID}
|
|
||||||
setWorkspaceID={setWorkspaceID}
|
|
||||||
|
|
||||||
projectID={projectID}
|
|
||||||
setProjectID={setProjectID}
|
|
||||||
|
|
||||||
darkMode={darkMode}
|
|
||||||
/>
|
/>
|
||||||
<Pomodoro
|
<Pomodoro
|
||||||
signedIn={signedIn}
|
signedIn={signedIn}
|
||||||
@@ -42,16 +39,7 @@ const Main = ({signedIn, darkMode, setKonamiCodeActive, KonamiCodeActive, notifi
|
|||||||
|
|
||||||
apiKey={apiKey}
|
apiKey={apiKey}
|
||||||
|
|
||||||
taskName={taskName}
|
clockifyData={clockifyData}
|
||||||
setTaskName={setTaskName}
|
|
||||||
|
|
||||||
workspaceID={workspaceID}
|
|
||||||
setWorkspaceID={setWorkspaceID}
|
|
||||||
|
|
||||||
projectID={projectID}
|
|
||||||
setProjectID={setProjectID}
|
|
||||||
|
|
||||||
darkMode={darkMode}
|
|
||||||
|
|
||||||
setKonamiCodeActive = {setKonamiCodeActive}
|
setKonamiCodeActive = {setKonamiCodeActive}
|
||||||
KonamiCodeActive= {KonamiCodeActive}
|
KonamiCodeActive= {KonamiCodeActive}
|
||||||
|
|||||||
@@ -27,18 +27,19 @@ const Pomodoro = (props) => {
|
|||||||
|
|
||||||
async function uploadToClockifyTimer() {
|
async function uploadToClockifyTimer() {
|
||||||
|
|
||||||
if (!props.workspaceID && !props.projectID) {
|
if (!props.clockifyData.workspaceID && !props.clockifyData.projectID) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const url = `https://api.clockify.me/api/v1/workspaces/${props.workspaceID}/time-entries`
|
const url = `https://api.clockify.me/api/v1/workspaces/${props.clockifyData.workspaceID}/time-entries`
|
||||||
|
|
||||||
const body = {
|
const body = {
|
||||||
start: startTime,
|
start: startTime,
|
||||||
end: endTime,
|
end: endTime,
|
||||||
projectId: props.projectID,
|
description: props.clockifyData.description,
|
||||||
description: props.taskName
|
projectId: props.clockifyData.projectID,
|
||||||
|
taskId: props.clockifyData.taskID ? props.clockifyData.taskID : "",
|
||||||
}
|
}
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
@@ -55,6 +56,7 @@ const Pomodoro = (props) => {
|
|||||||
await fetch(url, request)
|
await fetch(url, request)
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +70,7 @@ const Pomodoro = (props) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={props.darkMode ? 'main-pomodoro-container dark-mode-component' : 'main-pomodoro-container'}>
|
<div className='main-pomodoro-container' >
|
||||||
<div className="main-pomodoro">
|
<div className="main-pomodoro">
|
||||||
|
|
||||||
<PomodoroTimer
|
<PomodoroTimer
|
||||||
@@ -79,14 +81,6 @@ const Pomodoro = (props) => {
|
|||||||
|
|
||||||
stats={stats}
|
stats={stats}
|
||||||
setStats={setStats}
|
setStats={setStats}
|
||||||
|
|
||||||
workspaceID={props.workspaceID}
|
|
||||||
setWorkspaceID={props.setWorkspaceID}
|
|
||||||
|
|
||||||
projectID={props.projectID}
|
|
||||||
setProjectID={props.setProjectID}
|
|
||||||
|
|
||||||
apiKey={props.apiKey}
|
|
||||||
|
|
||||||
startTime={startTime}
|
startTime={startTime}
|
||||||
setStartTime={setStartTime}
|
setStartTime={setStartTime}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 29vh;
|
top: 29vh;
|
||||||
left: 75vw;
|
left: 75vw;
|
||||||
box-shadow: 1px 6px 15px #00000020;
|
box-shadow: 1px 6px 15px rgba(0, 0, 0, 0.1254901961);
|
||||||
z-index: 50;
|
z-index: 50;
|
||||||
transition: 0.2s ease-in-out;
|
transition: 0.2s ease-in-out;
|
||||||
}
|
}
|
||||||
@@ -109,6 +109,4 @@
|
|||||||
.style-selector .style-selection-container .style-container {
|
.style-selector .style-selection-container .style-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}/*# sourceMappingURL=style-selector.css.map */
|
||||||
|
|
||||||
/*# sourceMappingURL=style-selector.css.map */
|
|
||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"sourceRoot":"","sources":["style-selector.scss"],"names":[],"mappings":"AAAA;EAEI;EAEA;EACA;EAEA;EAEA;EACA;EAEA;EAEA;EAyEA;;AAvEA;EACI;EACA;EACA;EAEA;EACA;EACA;;AAIA;EACI;EACA;EAEA;;AAEA;EACI;EACA;EACA;EAEA;;AAEA;EACI;;AAGJ;EACI;EACA;;AAKZ;EACI;EACA;;AAGJ;EACI;EACA;;AAEA;EACI;;AAKR;EACI;EAEA;EACA;EAEA;EACA;EACA;EAEA;;AAGJ;EAEI;;;AASZ;EACI;EACA;;;AAGJ;EACI;EACA;;;AAGJ;EACI;IACI;IAEA;IAEA;IAEA;IACA;IAEA;;EAEA;IACI;IAEA;;EAIJ;IAEI;IAEA;IAEA;;EAEA;IACI;IACA;IAEA;;;AAMhB;EAEI;IAWI;;EATA;IACI;IAEA;;EAEA;IACI;;;AAQhB;EAMY;IACI","file":"style-selector.css"}
|
{"version":3,"sources":["style-selector.scss","style-selector.css"],"names":[],"mappings":"AAAA;EAEI,uBAAA;EAEA,iBAAA;EACA,oBAAA;EAEA,kBAAA;EAEA,SAAA;EACA,UAAA;EAEA,oDAAA;EAEA,WAAA;EAyEA,4BAAA;AC7EJ;ADMI;EACI,6BAAA;EACA,eAAA;EACA,kBAAA;EAEA,iBAAA;EACA,eAAA;EACA,kBAAA;ACLR;ADSQ;EACI,aAAA;EACA,YAAA;EAEA,mBAAA;ACRZ;ADUY;EACI,aAAA;EACA,sBAAA;EACA,uBAAA;EAEA,+BAAA;ACThB;ADWgB;EACI,eAAA;ACTpB;ADYgB;EACI,8BAAA;EACA,eAAA;ACVpB;ADeQ;EACI,WAAA;EACA,UAAA;ACbZ;ADgBQ;EACI,aAAA;EACA,+BAAA;ACdZ;ADgBY;EACI,mBAAA;ACdhB;ADmBQ;EACI,oBAAA;EAEA,WAAA;EACA,YAAA;EAEA,wCAAA;EACA,qBAAA;EACA,mBAAA;EAEA,4BAAA;ACpBZ;ADuBQ;EAEI,uCAAA;ACtBZ;;AD+BA;EACI,UAAA;EACA,oBAAA;AC5BJ;;AD+BA;EACI,UAAA;EACA,oBAAA;AC5BJ;;AD+BA;EACI;IACI,iBAAA;IAEA,gBAAA;IAEA,WAAA;IAEA,UAAA;IACA,gBAAA;IAEA,sBAAA;EChCN;EDkCM;IACI,iBAAA;IAEA,cAAA;ECjCV;EDqCM;IAEI,aAAA;IAEA,eAAA;IAEA,WAAA;ECtCV;EDwCU;IACI,YAAA;IACA,UAAA;IAEA,cAAA;ECvCd;AACF;AD4CA;EAEI;IAWI,kBAAA;ECrDN;ED4CM;IACI,iBAAA;IAEA,sBAAA;EC3CV;ED6CU;IACI,UAAA;EC3Cd;AACF;ADkDA;EAMY;IACI,WAAA;ECrDd;AACF","file":"style-selector.css"}
|
||||||
Reference in New Issue
Block a user