diff --git a/CHANGELOG.md b/CHANGELOG.md index 973f5bf..bfe39cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## version 2.4.1 + +- 简易 remark 功能, 用于回忆思考过程? 后续需要用这个数据生成文章 + ## version 2.3.2 - WC320 数据 diff --git a/README.md b/README.md index 3c17c3e..cecb408 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ - [新增区块测试用例](#区块测试用例) - [新增搬砖功能(重复练习?)](#搬砖功能的说明) - [状态栏增加简易计时器](#状态栏增加简易计时器) +- [新增一个 remark 功能](#新增在工作目录存放数据) # 关于本项目 @@ -100,6 +101,10 @@ > > .lcpr_data/ 存数据 > > > > > bricks.json + > > + > > > remark 备注数据 + > > > + > > > > qid 备注 remark 数据 ### bricks.json 存放格式 diff --git a/package.json b/package.json index 986c305..d13e0ea 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-leetcode-problem-rating", "displayName": "LeetCode", "description": "LeetCode 官方插件增强, 代码开源, 增加 LeetCode 题目难度分, 给个star吧, 球球了", - "version": "2.3.2", + "version": "2.4.1", "author": "ccagml", "publisher": "ccagml", "license": "MIT", @@ -184,41 +184,43 @@ "icon": "$(sort-precedence)" }, { - "command": "mywiki.commentcreateNote", - "title": "Create Note", - "enablement": "!commentIsEmpty" + "command": "lcpr.remarkCreateNote", + "title": "Create Note" }, { - "command": "mywiki.commentreplyNote", - "title": "Reply", - "enablement": "!commentIsEmpty" + "command": "lcpr.remarkClose", + "title": "关闭?" }, { - "command": "mywiki.commenteditNote", - "title": "Edit", + "command": "lcpr.remarkReplyNote", + "title": "New Note" + }, + { + "command": "lcpr.remarkEditNote", + "title": "Edit Note", "icon": { "dark": "resources/edit_inverse.svg", "light": "resources/edit.svg" } }, { - "command": "mywiki.commentdeleteNoteComment", - "title": "Delete", + "command": "lcpr.remarkDeleteNoteComment", + "title": "Delete Note", "icon": { "dark": "resources/close_inverse.svg", "light": "resources/close.svg" } }, { - "command": "mywiki.commentsaveNote", - "title": "Save" + "command": "lcpr.remarkSaveNote", + "title": "Save Note" }, { - "command": "mywiki.commentcancelsaveNote", - "title": "Cancel" + "command": "lcpr.remarkCancelsaveNote", + "title": "Cancel Note" }, { - "command": "mywiki.commentdispose", + "command": "lcpr.remarkDispose", "title": "Remove All Notes" } ], @@ -246,53 +248,54 @@ "menus": { "commandPalette": [ { - "command": "mywiki.commentcreateNote", - "when": "false" + "command": "lcpr.remarkCreateNote", + "when": "true" }, { - "command": "mywiki.commentreplyNote", - "when": "false" + "command": "lcpr.remarkReplyNote", + "when": "true" }, { - "command": "mywiki.commentdeleteNoteComment", - "when": "false" + "command": "lcpr.remarkDeleteNoteComment", + "when": "true" + } + ], + "comments/commentThread/title": [ + { + "command": "lcpr.remarkClose", + "group": "inline", + "when": "commentController == comment-sample" } ], - "comments/commentThread/title": [], "comments/commentThread/context": [ { - "command": "mywiki.commentcreateNote", + "command": "lcpr.remarkCreateNote", "group": "inline", "when": "commentController == comment-sample && commentThreadIsEmpty" }, { - "command": "mywiki.commentreplyNote", + "command": "lcpr.remarkReplyNote", "group": "inline", "when": "commentController == comment-sample && !commentThreadIsEmpty" } ], "comments/comment/title": [ { - "command": "mywiki.commenteditNote", + "command": "lcpr.remarkEditNote", "group": "group@1", "when": "commentController == comment-sample" }, { - "command": "mywiki.commentdeleteNoteComment", + "command": "lcpr.remarkDeleteNoteComment", "group": "group@2", "when": "commentController == comment-sample && comment == canDelete" } ], "comments/comment/context": [ { - "command": "mywiki.commentcancelsaveNote", + "command": "lcpr.remarkSaveNote", "group": "inline@1", "when": "commentController == comment-sample" - }, - { - "command": "mywiki.commentsaveNote", - "group": "inline@2", - "when": "commentController == comment-sample" } ], "view/title": [ diff --git a/src/controller/RemarkController.ts b/src/controller/RemarkController.ts new file mode 100644 index 0000000..d47b76d --- /dev/null +++ b/src/controller/RemarkController.ts @@ -0,0 +1,48 @@ +/* + * Filename: /home/cc/vscode-leetcode-problem-rating/src/controller/RemarkController.ts + * Path: /home/cc/vscode-leetcode-problem-rating + * Created Date: Monday, November 28th 2022, 3:29:37 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ + +import { CommentReply, Disposable, TextDocument } from "vscode"; +import { RemarkComment } from "../model/Model"; +import { remarkService } from "../service/RemarkService"; + +// 视图控制器 +class RemarkController implements Disposable { + public dispose(): void {} + + public remarkClose(a) { + remarkService.remarkClose(a); + } + + public remarkCreateNote(reply: CommentReply) { + remarkService.remarkCreateNote(reply); + } + + public remarkReplyNote(reply: CommentReply) { + remarkService.remarkReplyNote(reply); + } + + public remarkDeleteNoteComment(comment: RemarkComment) { + remarkService.remarkDeleteNoteComment(comment); + } + public async startRemark(document: TextDocument) { + await remarkService.startRemark(document); + } + + public remarkCancelsaveNote(comment: RemarkComment) { + remarkService.remarkCancelsaveNote(comment); + } + public remarkSaveNote(comment: RemarkComment) { + remarkService.remarkSaveNote(comment); + } + public remarkEditNote(comment: RemarkComment) { + remarkService.remarkEditNote(comment); + } +} + +export const remarkController: RemarkController = new RemarkController(); diff --git a/src/controller/TreeViewController.ts b/src/controller/TreeViewController.ts index 58a3971..bc817e5 100644 --- a/src/controller/TreeViewController.ts +++ b/src/controller/TreeViewController.ts @@ -1391,6 +1391,10 @@ class TreeViewController implements Disposable { return this.getNodeById(this.qidToFid.get(qid) || ""); } + public getQidByFid(id: string) { + return this.fidToQid.get(id); + } + public getFavoriteNodes(): NodeModel[] { const res: NodeModel[] = []; for (const node of this.explorerNodeMap.values()) { diff --git a/src/dao/remarkDao.ts b/src/dao/remarkDao.ts new file mode 100644 index 0000000..2984761 --- /dev/null +++ b/src/dao/remarkDao.ts @@ -0,0 +1,85 @@ +// > workspace/ 工作目录 +// > +// > > .lcpr_data/ 存数据 +// > > +// > > > remake/ 备注 +// > > > +// > > > > 题目内部编号.json 根据 qid 备注的信息 +// > > + +import { fetchProblemLanguage, selectWorkspaceFolder } from "../utils/ConfigUtils"; +import { useWsl, toWinPath } from "../utils/SystemUtils"; +import * as path from "path"; +import * as fse from "fs-extra"; + +class RemarkDao { + version = 1; + public async get_remark_dir_path() { + const language: string | undefined = await fetchProblemLanguage(); + if (!language) { + return; + } + const workspaceFolder: string = await selectWorkspaceFolder(false); + if (!workspaceFolder) { + return; + } + let lcpr_data_path: string = path.join(workspaceFolder, ".lcpr_data"); + await fse.ensureDir(lcpr_data_path); + + let remark_dir: string = path.join(lcpr_data_path, "remark"); + await fse.ensureDir(remark_dir); + + remark_dir = useWsl() ? await toWinPath(remark_dir) : remark_dir; + return remark_dir; + } + public async init() { + let lcpr_data_path = await this.get_remark_dir_path(); + if (!lcpr_data_path) { + return; + } + } + + private async getQidPath(qid: string) { + let remark_dir = await this.get_remark_dir_path(); + if (!remark_dir) { + return; + } + if (!qid) { + return; + } + let qid_path: string = path.join(remark_dir, qid); + qid_path = useWsl() ? await toWinPath(qid_path) : qid_path; + return qid_path; + } + + private async _write_data(qid: string, data: object) { + let qid_data_path = await this.getQidPath(qid); + if (!qid_data_path) { + return; + } + return await fse.writeFile(qid_data_path, JSON.stringify(data)); + } + + private async _read_data(qid: string) { + let qid_data_path = await this.getQidPath(qid); + if (!qid_data_path) { + return; + } + + if (!(await fse.pathExists(qid_data_path))) { + return {}; + } + let temp_data = await fse.readFile(qid_data_path, "utf8"); + return JSON.parse(temp_data) || {}; + } + + public async getInfoByQid(qid: string) { + let all_remark = await this._read_data(qid); + return all_remark || {}; + } + public async setInfoByQid(qid: string, info) { + await this._write_data(qid, info); + } +} + +export const remarkDao: RemarkDao = new RemarkDao(); diff --git a/src/extension.ts b/src/extension.ts index 2a24103..0d543e3 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -7,27 +7,7 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { - ExtensionContext, - window, - commands, - Uri, - // MarkdownString, - // CommentMode, - // CommentAuthorInformation, - // CommentThread, - // Comment, - // CommentReply, - // CommentThreadCollapsibleState, - // CommentReaction, - // CommentController, - // CommentingRangeProvider, - // CommentOptions, - // TextDocument, - // CancellationToken, - // comments, - // Range, -} from "vscode"; +import { ExtensionContext, window, commands, Uri, CommentReply, TextDocument } from "vscode"; import { fileButtonController } from "./controller/FileButtonController"; import { treeViewController } from "./controller/TreeViewController"; import { NodeModel } from "./model/NodeModel"; @@ -44,26 +24,12 @@ import { markdownService } from "./service/MarkdownService"; import { mainContorller } from "./controller/MainController"; import { loginContorller } from "./controller/LoginController"; import { getLeetCodeEndpoint } from "./utils/ConfigUtils"; -import { BricksType, OutPutType } from "./model/Model"; +import { BricksType, OutPutType, RemarkComment } from "./model/Model"; import { bricksDataService } from "./service/BricksDataService"; import { bricksViewController } from "./controller/BricksViewController"; import { statusBarTimeService } from "./service/StatusBarTimeService"; +import { remarkController } from "./controller/RemarkController"; -// let commentId = 1; - -// class NoteComment implements Comment { -// id: number; -// label: string | undefined; -// constructor( -// public body: string | MarkdownString, -// public mode: CommentMode, -// public author: CommentAuthorInformation, -// public parent?: CommentThread, -// public contextValue?: string -// ) { -// this.id = ++commentId; -// } -// } // 激活插件 /** * The main function of the extension. It is called when the extension is activated. @@ -138,7 +104,32 @@ export async function activate(context: ExtensionContext): Promise { ), commands.registerCommand("lcpr.setBricksType6", (node: NodeModel) => bricksViewController.setBricksType(node, BricksType.TYPE_6) - ) + ), + + commands.registerCommand("lcpr.remarkCreateNote", (reply: CommentReply) => { + remarkController.remarkCreateNote(reply); + }), + commands.registerCommand("lcpr.remarkClose", (a) => { + remarkController.remarkClose(a); + }), + commands.registerCommand("lcpr.remarkReplyNote", (reply: CommentReply) => { + remarkController.remarkReplyNote(reply); + }), + commands.registerCommand("lcpr.remarkDeleteNoteComment", (comment: RemarkComment) => { + remarkController.remarkDeleteNoteComment(comment); + }), + commands.registerCommand("lcpr.remarkCancelsaveNote", (comment: RemarkComment) => { + remarkController.remarkCancelsaveNote(comment); + }), + commands.registerCommand("lcpr.remarkSaveNote", (comment: RemarkComment) => { + remarkController.remarkSaveNote(comment); + }), + commands.registerCommand("lcpr.remarkEditNote", (comment: RemarkComment) => { + remarkController.remarkEditNote(comment); + }), + commands.registerCommand("lcpr.startRemark", (document: TextDocument) => { + remarkController.startRemark(document); + }) ); // 设置站点 @@ -146,120 +137,6 @@ export async function activate(context: ExtensionContext): Promise { // 获取登录状态 await loginContorller.getLoginStatus(); await bricksViewController.initialize(); - // let aaa; - // // A `CommentController` is able to provide comments for documents. - // const commentController = comments.createCommentController("comment-sample", "Comment API Sample"); - // commentController.commentingRangeProvider = { - // provideCommentingRanges: (document: TextDocument, token: CancellationToken) => { - // let lineCount = document.lineCount; - // aaa = commentController.createCommentThread(document.uri, new Range(5, 0, 10, 0), []); - // aaa.dispose = () => { - // let cac = aaa; - // console.log("ssss"); - // }; - // console.log(aaa); - // return undefined; - // }, - // }; - // let bbb; - // commands.registerCommand("lcpr.previewProblem", (a, b, c) => { - // bbb = commentController.createCommentThread(a, new Range(5, 0, 10, 0), [ - // new NoteComment("ssss", CommentMode.Preview, { name: "vscode" }), - // // new NoteComment("bbbb", CommentMode.Preview, { name: "vscode" }), - // ]); - // }), - // context.subscriptions.push(commentController); - - // context.subscriptions.push( - // commands.registerCommand("mywiki.commentcreateNote", (reply: CommentReply) => { - // replyNote(reply); - // }) - // ); - - // context.subscriptions.push( - // commands.registerCommand("mywiki.commentreplyNote", (reply: CommentReply) => { - // replyNote(reply); - // }) - // ); - - // context.subscriptions.push( - // commands.registerCommand("mywiki.commentdeleteNoteComment", (comment: NoteComment) => { - // let thread = comment.parent; - // if (!thread) { - // return; - // } - - // thread.comments = thread.comments.filter((cmt) => (cmt as NoteComment).id !== comment.id); - - // if (thread.comments.length === 0) { - // thread.dispose(); - // } - // }) - // ); - - // context.subscriptions.push( - // commands.registerCommand("mywiki.commentcancelsaveNote", (comment: NoteComment) => { - // if (!comment.parent) { - // return; - // } - - // comment.parent.comments = comment.parent.comments.map((cmt) => { - // if ((cmt as NoteComment).id === comment.id) { - // cmt.mode = CommentMode.Preview; - // } - - // return cmt; - // }); - // }) - // ); - - // context.subscriptions.push( - // commands.registerCommand("mywiki.commentsaveNote", (comment: NoteComment) => { - // if (!comment.parent) { - // return; - // } - - // comment.parent.comments = comment.parent.comments.map((cmt) => { - // if ((cmt as NoteComment).id === comment.id) { - // cmt.mode = CommentMode.Preview; - // } - - // return cmt; - // }); - // }) - // ); - - // context.subscriptions.push( - // commands.registerCommand("mywiki.commenteditNote", (comment: NoteComment) => { - // if (!comment.parent) { - // return; - // } - - // comment.parent.comments = comment.parent.comments.map((cmt) => { - // if ((cmt as NoteComment).id === comment.id) { - // cmt.mode = CommentMode.Editing; - // } - - // return cmt; - // }); - // }) - // ); - - // function replyNote(reply: CommentReply) { - // let thread = reply.thread; - // let newComment = new NoteComment( - // reply.text, - // CommentMode.Preview, - // { name: "vscode" }, - // thread, - // thread.comments.length ? "canDelete" : undefined - // ); - // if (thread.contextValue === "draft") { - // newComment.label = "pending"; - // } - - // thread.comments = [...thread.comments, newComment]; - // } } catch (error) { logOutput.appendLine(error.toString()); promptForOpenOutputChannel( diff --git a/src/model/Model.ts b/src/model/Model.ts index f549fb3..d869157 100644 --- a/src/model/Model.ts +++ b/src/model/Model.ts @@ -7,7 +7,17 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { ViewColumn, QuickPickItem, MessageItem } from "vscode"; +import { + ViewColumn, + QuickPickItem, + MessageItem, + Comment, + MarkdownString, + CommentMode, + CommentAuthorInformation, + CommentThread, +} from "vscode"; +import { getDayNowM, getRemakeName } from "../utils/SystemUtils"; export interface IQuickItemEx extends QuickPickItem { value: T; @@ -259,6 +269,38 @@ export interface ISubmitEvent { accepted: boolean; } +export class RemarkComment implements Comment { + id: number; + label: string | undefined; + mode: CommentMode; + author: CommentAuthorInformation; + contextValue?: string; + + constructor(public body: string | MarkdownString, public parent?: CommentThread) { + this.id = getDayNowM(); + this.label = ""; + this.contextValue = "canDelete"; + this.mode = CommentMode.Preview; + this.author = { name: getRemakeName() }; + } + + getDbData() { + let a = { + name: this.author.name, + id: this.id, + body: this.body, + }; + return a; + } + + static getObjByDbData(dbData, thread?): RemarkComment { + let obj = new RemarkComment(dbData.body, thread); + obj.id = dbData.id || getDayNowM(); + obj.author = { name: dbData.name }; + return obj; + } +} + export interface IWebViewOption { title: string; viewColumn: ViewColumn; diff --git a/src/service/FileButtonService.ts b/src/service/FileButtonService.ts index 4a67c26..7e5edea 100644 --- a/src/service/FileButtonService.ts +++ b/src/service/FileButtonService.ts @@ -137,6 +137,21 @@ export class FileButtonService implements vscode.CodeLensProvider { typescript: "//", }; + public processRemarkButton(codeLensLine, document): vscode.CodeLens[] { + const temp_result: vscode.CodeLens[] = []; + + const range: vscode.Range = new vscode.Range(codeLensLine, 0, codeLensLine, 0); + + temp_result.push( + new vscode.CodeLens(range, { + title: "remark", + command: "lcpr.startRemark", + arguments: [document], + }) + ); + return temp_result; + } + public provideCodeLenses(document: vscode.TextDocument): vscode.ProviderResult { const content: string = document.getText(); const matchResult: RegExpMatchArray | null = content.match(/@lc app=.* id=(.*) lang=.*/); @@ -158,6 +173,10 @@ export class FileButtonService implements vscode.CodeLensProvider { this.processCodeButton(i, document, node).forEach((x) => codeLens.push(x)); } + if (lineContent.indexOf("@lc code=start") >= 0) { + this.processRemarkButton(i, document).forEach((x) => codeLens.push(x)); + } + if (caseFlag && lineContent.indexOf("@lcpr case=end") < 0) { curCase += lineContent.replace(/#/g, "").replace(/\/\//g, "").replace(/--/g, "").replace(/\s+/g, ""); } diff --git a/src/service/RemarkService.ts b/src/service/RemarkService.ts new file mode 100644 index 0000000..d57e685 --- /dev/null +++ b/src/service/RemarkService.ts @@ -0,0 +1,169 @@ +import { + CommentMode, + CommentThread, + CommentReply, + CommentThreadCollapsibleState, + TextDocument, + CancellationToken, + comments, + Range, + Disposable, +} from "vscode"; +import { treeViewController } from "../controller/TreeViewController"; +import { remarkDao } from "../dao/remarkDao"; +import { RemarkComment } from "../model/Model"; + +class RemarkService implements Disposable { + private _remarkComment; + private _qid_map_thread: Map; + + getQidByDocument(document: TextDocument) { + const content: string = document.getText(); + const matchResult: RegExpMatchArray | null = content.match(/@lc app=.* id=(.*) lang=.*/); + let result: Map = new Map(); + if (!matchResult) { + return result; + } + const fid: string | undefined = matchResult[1]; + let qid: string | undefined = treeViewController.getQidByFid(fid); + result["fid"] = fid; + if (qid != undefined) { + result["qid"] = qid.toString(); + } + return result; + } + + constructor() { + this._qid_map_thread = new Map(); + this._remarkComment = comments.createCommentController("comment-sample", "Comment API Sample"); + this._remarkComment.options = { prompt: "新的记录", placeHolder: "开始记录内容" }; + this._remarkComment.commentingRangeProvider = { + provideCommentingRanges: (_: TextDocument, __: CancellationToken) => { + return undefined; + }, + }; + } + + public async startRemark(document: TextDocument) { + let docInfo = this.getQidByDocument(document); + if (docInfo["qid"] == undefined) { + return; + } + if (this._qid_map_thread.get(docInfo["qid"]) != undefined) { + // 已经有了 + this._qid_map_thread.get(docInfo["qid"])?.dispose(); + this._qid_map_thread.delete(docInfo["qid"]); + } + let oldRemark = await this.getOldThreadRemarkByQid(docInfo["qid"]); + for (let i: number = 0; i < document.lineCount; i++) { + const lineContent: string = document.lineAt(i).text; + if (lineContent.indexOf("@lc code=start") >= 0) { + let newRemark = this._remarkComment.createCommentThread(document.uri, new Range(i - 1, 0, i - 1, 0), oldRemark); + newRemark.comments.forEach((element) => { + element.parent = newRemark; + }); + + newRemark.contextValue = `qid=${docInfo["qid"]}`; + newRemark.label = `${docInfo["fid"]}`; + newRemark.collapsibleState = CommentThreadCollapsibleState.Expanded; + this._qid_map_thread.set(docInfo["qid"], newRemark); + break; + } + } + } + + public remarkCreateNote(reply: CommentReply) { + this.replyNote(reply); + } + + public remarkReplyNote(reply: CommentReply) { + this.replyNote(reply); + } + + public remarkDeleteNoteComment(comment: RemarkComment) { + if (!comment.parent) { + return; + } + + comment.parent.comments = comment.parent.comments.filter((cmt) => (cmt as RemarkComment).id !== comment.id); + this.saveThreadRemark(comment.parent); + } + + public remarkCancelsaveNote(comment: RemarkComment) { + if (!comment.parent) { + return; + } + + comment.parent.comments = comment.parent.comments.map((cmt) => { + if ((cmt as RemarkComment).id === comment.id) { + cmt.mode = CommentMode.Preview; + } + + return cmt; + }); + this.saveThreadRemark(comment.parent); + } + public remarkSaveNote(comment: RemarkComment) { + this.remarkCancelsaveNote(comment); + } + public remarkEditNote(comment: RemarkComment) { + if (!comment.parent) { + return; + } + + comment.parent.comments = comment.parent.comments.map((cmt) => { + if ((cmt as RemarkComment).id === comment.id) { + cmt.mode = CommentMode.Editing; + } + + return cmt; + }); + + this.saveThreadRemark(comment.parent); + } + + public replyNote(reply: CommentReply) { + let thread = reply.thread; + let newComment = new RemarkComment(reply.text, thread); + thread.comments = [...thread.comments, newComment]; + this.saveThreadRemark(thread); + } + + public saveThreadRemark(thread) { + const params: URLSearchParams = new URLSearchParams(thread.contextValue); + let qid = params.get("qid"); + if (!qid) { + return; + } + let data: Array = []; + thread.comments.forEach((element) => { + data.push(element.getDbData()); + }); + let remarkData = {}; + remarkData["data"] = data; + remarkDao.setInfoByQid(qid, remarkData); + } + public async getOldThreadRemarkByQid(qid: string, thread?) { + let remarkData = await remarkDao.getInfoByQid(qid); + let remarkDataBody = remarkData["data"] || []; + let OldRemark: Array = []; + remarkDataBody.forEach((element) => { + OldRemark.push(RemarkComment.getObjByDbData(element, thread)); + }); + return OldRemark; + } + + public remarkClose(thread) { + const params: URLSearchParams = new URLSearchParams(thread.contextValue); + let qid = params.get("qid"); + if (!qid) { + return; + } + + this._qid_map_thread.get(qid)?.dispose(); + } + + public dispose(): void {} +} + +export const remarkService: RemarkService = new RemarkService(); diff --git a/src/utils/SystemUtils.ts b/src/utils/SystemUtils.ts index 5458ed9..84bd6ff 100644 --- a/src/utils/SystemUtils.ts +++ b/src/utils/SystemUtils.ts @@ -84,3 +84,20 @@ export function getDayEnd(): number { export function getDayNow(): number { return Math.round(new Date().getTime() / 1000); } + +export function getDayNowM(): number { + return Math.round(new Date().getTime()); +} + +export function getRemakeName(): string { + const date = new Date(); + const year = date.getFullYear(); + const month = date.getMonth() + 1 >= 10 ? date.getMonth() + 1 : `0${date.getMonth() + 1}`; + const day = date.getDate() >= 10 ? date.getDate() : `0${date.getDate()}`; + const hours = date.getHours() >= 10 ? date.getHours() : `0${date.getHours()}`; + const min = date.getMinutes() >= 10 ? date.getMinutes() : `0${date.getMinutes()}`; + const s = date.getSeconds() >= 10 ? date.getSeconds() : `0${date.getSeconds()}`; + + const newDate = `${year}-${month}-${day} ${hours}:${min}:${s}`; + return newDate; +}