diff --git a/typescript/clockify/README.md b/typescript/clockify/README.md new file mode 100644 index 0000000..928c2fa --- /dev/null +++ b/typescript/clockify/README.md @@ -0,0 +1,52 @@ +# Clockify entry adder + +Sequence which daily adds a new entry in Clockify + +> ❗ By default this code adds 5 same entries for all weekdays. For weekends it adds new entries with 0 hours on them. + +## Requirements + +You need to have a [clockify account](https://app.clockify.me/signup) and a [access key](https://clockify.me/help/faq/where-can-i-find-api-information) + +You also need to have scramjet cli installed, for guide how to install [visit our documentation](https://docs.scramjet.org/platform/get-started/) +## Preparations + +Before running the code enter valid data in `data.json`, you need to fill all options to make the code working. For more informations how to get those details visit [Clockify Api documentation](https://docs.clockify.me/). + +```json +{ + "workspace":"WORKSPACE-ID", + "weekDayProjectId":"WEEKDAY-PROJECT-ID", + "satProjectId":"SATURDAY-PROJECT-ID", + "sunProjectId":"SUNDAY-PROJECT-ID", + "startHour": 9,//Start hour here in 24h format without leading 0 and minutes + "endHour" : 17,//End hour here in 24h format without leading 0 and minutes + "satStartHour": 9, + "satEndHour":9, + "sunStartHour": 9, + "sunEndHour": 9 +} + +``` + +## Running + +To start the sequence simply run those commands in your terminal: + + +```bash +# go to sample directory +cd typescript/clockify + +# install dependencies +npm install + +# transpile TS->JS and copy node_modules and package.json to dist/ +npm run build + +# deploy the Sequence from the dist/ directory, which contains transpiled code, package.json and node_modules +si sequence deploy dist --args [1,\"key\"] + +``` + +After completeing all steps the instance should be running and adding new entries to clockify daily. diff --git a/typescript/clockify/data.json b/typescript/clockify/data.json new file mode 100644 index 0000000..0472d35 --- /dev/null +++ b/typescript/clockify/data.json @@ -0,0 +1,12 @@ +{ + "workspace":"WORKSPACE-ID", + "weekDayProjectId":"WEEKDAY-PROJECT-ID", + "satProjectId":"SATURDAY-PROJECT-ID", + "sunProjectId":"SUNDAY-PROJECT-ID", + "startHour": 9, + "endHour" : 17, + "satStartHour": 9, + "satEndHour":9, + "sunStartHour": 9, + "sunEndHour": 9 +} diff --git a/typescript/clockify/index.ts b/typescript/clockify/index.ts new file mode 100644 index 0000000..8fdee0b --- /dev/null +++ b/typescript/clockify/index.ts @@ -0,0 +1,26 @@ +/* eslint-disable no-console */ +import { ClockifyEntryBuilder } from "./utils/clockifyEntryBuilder"; +import { ReadableApp } from "@scramjet/types"; + +const app: ReadableApp = async function( + _stream, + interval:number = 1000 * 60 * 60 * 24, + apiKey:string) { + this.logger.info("starting instance which adds clockify entry daily"); + const entryBuilder = new ClockifyEntryBuilder(); + entryBuilder.setApiKey(apiKey); + + entryBuilder.setDate(new Date()); + await entryBuilder.sendRequest() + .then((res) => this.logger.info(res)); + + setInterval(async () => { + entryBuilder.setDate(new Date()); + await entryBuilder.sendRequest() + .then((res) => this.logger.info(res)); + }, interval); + + return new Promise((_res, _rej) => { }); +}; + +export default app; diff --git a/typescript/clockify/package.json b/typescript/clockify/package.json new file mode 100644 index 0000000..a720871 --- /dev/null +++ b/typescript/clockify/package.json @@ -0,0 +1,30 @@ +{ + "name": "@scramjet/clockify", + "version": "1.0.0", + "description": "Sequence which adds new entries to clickup on a daily basis", + "main": "index.js", + "scripts": { + "build": "tsc -p tsconfig.json", + "postbuild": "cp -r package.json dist/ && (cd dist && npm i --only=production)", + "pack": "si seq pack ./dist/", + "clean": "rm -rf ./dist ./*.tar.gz" + }, + "keywords": [ + "API", + "clockify", + "HTTP" + ], + "repository": { + "type": "git", + "url": "https://github.com/scramjetorg/platform-samples/tree/main/typescript/clockify" + }, + "author": "Piotr", + "license": "GPL-3.0", + "dependencies": { + "date-and-time": "^2.4.3" + }, + "devDependencies": { + "@types/node": "15.12.5", + "@scramjet/types": "0.33.4" + } +} diff --git a/typescript/clockify/tsconfig.json b/typescript/clockify/tsconfig.json new file mode 100644 index 0000000..6c5b594 --- /dev/null +++ b/typescript/clockify/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "lib": [ "ESNext" ], + "target": "ESNext", + "module": "CommonJS", + "outDir": "./dist", + "esModuleInterop": true, + "skipLibCheck": true, + "resolveJsonModule": true, + } + +} diff --git a/typescript/clockify/utils/clockify.ts b/typescript/clockify/utils/clockify.ts new file mode 100644 index 0000000..fdee6b8 --- /dev/null +++ b/typescript/clockify/utils/clockify.ts @@ -0,0 +1,53 @@ +/* eslint-disable no-console */ +import * as data from "../data.json"; +import { request } from "https"; +import { ClientRequest } from "http"; + +type clockifyTimeEntry = { + startTime:Date, + endTime:Date, + projectId:string +} +export class ClockifyClient { + apiKey:string; + workspace:string = data.workspace; + options; + setApiKey(apiKey:string) { + this.apiKey = apiKey; + this.options = { + hostname: "api.clockify.me", + path: `/api/v1/workspaces/${data.workspace}/time-entries`, + port: 443, + headers: { + "X-Api-Key": apiKey, + "content-type": "application/json" + }, + method: "POST", + }; + } + async sendRequest(info:clockifyTimeEntry) :Promise { + const body = JSON.stringify({ + billable:"false", + end: info.endTime, + projectId: info.projectId, + start:info.startTime + }); + + console.log(body); + + const req:ClientRequest = request(this.options, (res) => { + console.log("statusCode:", res.statusCode); + }); + + return new Promise((res, rej) => { + req.on("error", (e) => { + rej(e); + }); + req.on("end", () => { + res("succesfully added new entry "); + }); + req.write(body); + req.end(); + }); + } +} diff --git a/typescript/clockify/utils/clockifyEntryBuilder.ts b/typescript/clockify/utils/clockifyEntryBuilder.ts new file mode 100644 index 0000000..6b4d3da --- /dev/null +++ b/typescript/clockify/utils/clockifyEntryBuilder.ts @@ -0,0 +1,50 @@ +/* eslint-disable no-async-promise-executor */ +/* eslint-disable max-len */ +import * as data from "../data.json"; +import { ClockifyClient } from "./clockify"; + +export class ClockifyEntryBuilder { + clockifyClient = new ClockifyClient(); + day:Date; + + setDate(day:Date) { + this.day = day; + this.day.setMinutes(0); + this.day.setSeconds(0); + this.day.setMilliseconds(0); + } + setApiKey(apiKey:string){ + this.clockifyClient.setApiKey(apiKey); + } + setTime(time:number):Date { + return new Date(this.day.setHours(time)); + } + async sendRequest():Promise { + const start = this.setTime(data.startHour); + + return new Promise(async (res, rej) => { + try { + switch (this.day.getDay()) { + case 0: + await this.clockifyClient.sendRequest({ startTime:this.setTime(data.sunStartHour), endTime:this.setTime(data.sunEndHour), projectId:data.sunProjectId }); + res("request sent for Sunday"); + break; + case 6: + await this.clockifyClient.sendRequest({ startTime:this.setTime(data.satStartHour), endTime:this.setTime(data.satEndHour), projectId:data.satProjectId }); + res("request sent for Saturday"); + break; + default: + const end = this.setTime(data.endHour); + + await this.clockifyClient.sendRequest({ startTime:start, endTime:end, projectId:data.weekDayProjectId }) + .then((response) => res(response)) + .catch((error) => rej(error)); + + break; + } + } catch (error) { + rej(error); + } + }); + } +}