clangd does not find `compile_commands.json` automatically - clangd

Setup
I'm using clangd through neovim with nvim-lspconfig.
require('lspconfig').clangd.setup {
-- on_attach = keybinds.on_attach,
cmd = {
"clangd",
"--background-index",
"--suggest-missing-includes",
-- "--compile-commands-dir=/home/localuser/test/build",
},
filetypes = { "c", "cpp", "objc", "objcpp" },
}
Problem
clangd is not finding project specific includes.
What it should be doing
According to the documentation: (https://clangd.llvm.org/installation.html)
clangd will look in the parent directories of the files you edit looking for it, and also in subdirectories named build/. For example, if editing $SRC/gui/window.cpp, we search in $SRC/gui/, $SRC/gui/build/, $SRC/, $SRC/build/, …
I've built the project with cmake flag -DCMAKE_EXPORT_COMPILE_COMMANDS=1 and i have compile_commands.json in the build directory: ~/test/build/compile_commands.json
The source file I am editing is ~/test/src/main.cpp
As per the documentation, clangd should find the compilation database from the build folder, as the build folder is in a parent folder of the source file, but it does not.
What is happening
clangd gives errors on includes. I've included the full ~/.local/state/nvim/lsp.log at the end.
I can explicitly show clangd where the JSON is with the --compile-commands-dir flag (commented in first code block), and then it does work. However that is a system-wide configuration so I don't want to do that (and according to the documentation I shouldn't have to)
I can also symlink ./build/compile_commands.json to ./compile_commands.json, and then clangd works correctly.
Logs
I've created a small example. Its basically just a main() function which includes the opencv library (required in CMakeLists.txt)
The project compiles just fine, but clangd complains that opencv2/opencv.hpp cannot be found.
Here's the test project directory layout:
localadmin#workstation:~/test$ tree
.
├── build
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   │   ├── 3.16.3
│   │   │   ├── CMakeCCompiler.cmake
│   │   │   ├── CMakeCXXCompiler.cmake
│   │   │   ├── CMakeDetermineCompilerABI_C.bin
│   │   │   ├── CMakeDetermineCompilerABI_CXX.bin
│   │   │   ├── CMakeSystem.cmake
│   │   │   ├── CompilerIdC
│   │   │   │   ├── a.out
│   │   │   │   ├── CMakeCCompilerId.c
│   │   │   │   └── tmp
│   │   │   └── CompilerIdCXX
│   │   │   ├── a.out
│   │   │   ├── CMakeCXXCompilerId.cpp
│   │   │   └── tmp
│   │   ├── cmake.check_cache
│   │   ├── CMakeDirectoryInformation.cmake
│   │   ├── CMakeOutput.log
│   │   ├── CMakeTmp
│   │   ├── Makefile2
│   │   ├── Makefile.cmake
│   │   ├── progress.marks
│   │   ├── TargetDirectories.txt
│   │   └── test.dir
│   │   ├── build.make
│   │   ├── cmake_clean.cmake
│   │   ├── CXX.includecache
│   │   ├── DependInfo.cmake
│   │   ├── depend.internal
│   │   ├── depend.make
│   │   ├── flags.make
│   │   ├── link.txt
│   │   ├── progress.make
│   │   └── src
│   │   └── main.cpp.o
│   ├── cmake_install.cmake
│   ├── compile_commands.json
│   ├── Makefile
│   └── test
├── build.sh
├── CMakeLists.txt
└── src
└── main.cpp
And here's the full lsp.log:
[START][2022-10-24 14:16:22] LSP logging initiated
[INFO][2022-10-24 14:16:22] .../vim/lsp/rpc.lua:662 "Starting RPC client" { args = { "--background-index", "--suggest-missing-includes" }, cmd = "clangd", extra = { cwd = "/home/localadmin/test" }}
[TRACE][2022-10-24 14:16:22] .../lua/vim/lsp.lua:1283 "LSP[clangd]" "initialize_params" { capabilities = { callHierarchy = { dynamicRegistration = false }, offsetEncoding = { "utf-8", "utf-16" }, textDocument = { codeAction = { codeActionLiteralSupport = { codeActionKind = { valueSet = { "", "Empty", "QuickFix", "Refactor", "RefactorExtract", "RefactorInline", "RefactorRewrite", "Source", "SourceOrganizeImports", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } } }, dataSupport = true, dynamicRegistration = false, isPreferredSupport = true, resolveSupport = { properties = { "edit" } } }, completion = { completionItem = { commitCharactersSupport = false, deprecatedSupport = false, documentationFormat = { "markdown", "plaintext" }, preselectSupport = false, snippetSupport = false }, completionItemKind = { valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } }, contextSupport = false, dynamicRegistration = false, editsNearCursor = true }, declaration = { linkSupport = true }, definition = { linkSupport = true }, documentHighlight = { dynamicRegistration = false }, documentSymbol = { dynamicRegistration = false, hierarchicalDocumentSymbolSupport = true, symbolKind = { valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } } }, hover = { contentFormat = { "markdown", "plaintext" }, dynamicRegistration = false }, implementation = { linkSupport = true }, publishDiagnostics = { relatedInformation = true, tagSupport = { valueSet = { 1, 2 } } }, references = { dynamicRegistration = false }, rename = { dynamicRegistration = false, prepareSupport = true }, signatureHelp = { dynamicRegistration = false, signatureInformation = { activeParameterSupport = true, documentationFormat = { "markdown", "plaintext" }, parameterInformation = { labelOffsetSupport = true } } }, synchronization = { didSave = true, dynamicRegistration = false, willSave = false, willSaveWaitUntil = false }, typeDefinition = { linkSupport = true } }, window = { showDocument = { support = false }, showMessage = { messageActionItem = { additionalPropertiesSupport = false } }, workDoneProgress = true }, workspace = { applyEdit = true, configuration = true, symbol = { dynamicRegistration = false, hierarchicalWorkspaceSymbolSupport = true, symbolKind = { valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } } }, workspaceEdit = { resourceOperations = { "rename", "create", "delete" } }, workspaceFolders = true } }, clientInfo = { name = "Neovim", version = "0.8.0" }, initializationOptions = vim.empty_dict(), processId = 377762, rootPath = "/home/localadmin/test", rootUri = "file:///home/localadmin/test", trace = "off", workspaceFolders = { { name = "/home/localadmin/test", uri = "file:///home/localadmin/test" } }}
[DEBUG][2022-10-24 14:16:22] .../vim/lsp/rpc.lua:285 "rpc.send" { id = 1, jsonrpc = "2.0", method = "initialize", params = { capabilities = { callHierarchy = { dynamicRegistration = false }, offsetEncoding = { "utf-8", "utf-16" }, textDocument = { codeAction = { codeActionLiteralSupport = { codeActionKind = { valueSet = { "", "Empty", "QuickFix", "Refactor", "RefactorExtract", "RefactorInline", "RefactorRewrite", "Source", "SourceOrganizeImports", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } } }, dataSupport = true, dynamicRegistration = false, isPreferredSupport = true, resolveSupport = { properties = { "edit" } } }, completion = { completionItem = { commitCharactersSupport = false, deprecatedSupport = false, documentationFormat = { "markdown", "plaintext" }, preselectSupport = false, snippetSupport = false }, completionItemKind = { valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } }, contextSupport = false, dynamicRegistration = false, editsNearCursor = true }, declaration = { linkSupport = true }, definition = { linkSupport = true }, documentHighlight = { dynamicRegistration = false }, documentSymbol = { dynamicRegistration = false, hierarchicalDocumentSymbolSupport = true, symbolKind = { valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } } }, hover = { contentFormat = { "markdown", "plaintext" }, dynamicRegistration = false }, implementation = { linkSupport = true }, publishDiagnostics = { relatedInformation = true, tagSupport = { valueSet = { 1, 2 } } }, references = { dynamicRegistration = false }, rename = { dynamicRegistration = false, prepareSupport = true }, signatureHelp = { dynamicRegistration = false, signatureInformation = { activeParameterSupport = true, documentationFormat = { "markdown", "plaintext" }, parameterInformation = { labelOffsetSupport = true } } }, synchronization = { didSave = true, dynamicRegistration = false, willSave = false, willSaveWaitUntil = false }, typeDefinition = { linkSupport = true } }, window = { showDocument = { support = false }, showMessage = { messageActionItem = { additionalPropertiesSupport = false } }, workDoneProgress = true }, workspace = { applyEdit = true, configuration = true, symbol = { dynamicRegistration = false, hierarchicalWorkspaceSymbolSupport = true, symbolKind = { valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } } }, workspaceEdit = { resourceOperations = { "rename", "create", "delete" } }, workspaceFolders = true } }, clientInfo = { name = "Neovim", version = "0.8.0" }, initializationOptions = vim.empty_dict(), processId = 377762, rootPath = "/home/localadmin/test", rootUri = "file:///home/localadmin/test", trace = "off", workspaceFolders = { { name = "/home/localadmin/test", uri = "file:///home/localadmin/test" } } }}
[ERROR][2022-10-24 14:16:22] .../vim/lsp/rpc.lua:734 "rpc" "clangd" "stderr" "I[14:16:22.583] clangd version 10.0.0-4ubuntu1
I[14:16:22.583] PID: 377766
I[14:16:22.583] Working directory: /home/localadmin/test
I[14:16:22.583] argv[0]: clangd
I[14:16:22.583] argv[1]: --background-index
I[14:16:22.583] argv[2]: --suggest-missing-includes
I[14:16:22.583] Starting LSP over stdin/stdout
I[14:16:22.584] <-- initialize(1)
I[14:16:22.584] --> reply:initialize(1) 0 ms
"
[DEBUG][2022-10-24 14:16:22] .../vim/lsp/rpc.lua:388 "rpc.receive" { id = 1, jsonrpc = "2.0", result = { capabilities = { codeActionProvider = { codeActionKinds = { "quickfix", "refactor", "info" } }, completionProvider = { resolveProvider = false, triggerCharacters = { ".", ">", ":" } }, declarationProvider = true, definitionProvider = true, documentFormattingProvider = true, documentHighlightProvider = true, documentLinkProvider = { resolveProvider = false }, documentOnTypeFormattingProvider = { firstTriggerCharacter = "
", moreTriggerCharacter = {} }, documentRangeFormattingProvider = true, documentSymbolProvider = true, executeCommandProvider = { commands = { "clangd.applyFix", "clangd.applyTweak" } }, hoverProvider = true, referencesProvider = true, renameProvider = { prepareProvider = true }, selectionRangeProvider = true, signatureHelpProvider = { triggerCharacters = { "(", "," } }, textDocumentSync = 2, typeHierarchyProvider = true, workspaceSymbolProvider = true }, offsetEncoding = "utf-8" }}
[DEBUG][2022-10-24 14:16:22] .../vim/lsp/rpc.lua:285 "rpc.send" { jsonrpc = "2.0", method = "initialized", params = vim.empty_dict()}
[INFO][2022-10-24 14:16:22] .../lua/vim/lsp.lua:1343 "LSP[clangd]" "server_capabilities" { server_capabilities = { codeActionProvider = { codeActionKinds = { "quickfix", "refactor", "info" } }, completionProvider = { resolveProvider = false, triggerCharacters = { ".", ">", ":" } }, declarationProvider = true, definitionProvider = true, documentFormattingProvider = true, documentHighlightProvider = true, documentLinkProvider = { resolveProvider = false }, documentOnTypeFormattingProvider = { firstTriggerCharacter = "
", moreTriggerCharacter = {} }, documentRangeFormattingProvider = true, documentSymbolProvider = true, executeCommandProvider = { commands = { "clangd.applyFix", "clangd.applyTweak" } }, hoverProvider = true, referencesProvider = true, renameProvider = { prepareProvider = true }, selectionRangeProvider = true, signatureHelpProvider = { triggerCharacters = { "(", "," } }, textDocumentSync = { change = 2, openClose = true, save = { includeText = false }, willSave = false, willSaveWaitUntil = false }, typeHierarchyProvider = true, workspaceSymbolProvider = true }}
[DEBUG][2022-10-24 14:16:22] .../vim/lsp/rpc.lua:285 "rpc.send" { jsonrpc = "2.0", method = "textDocument/didOpen", params = { textDocument = { languageId = "cpp", text = '#include <iostream>
#include "opencv2/opencv.hpp"
int main(int argc, char** argv ) {
if(argc != 2)
{
std::cerr << std::endl << "Usage: ./datacollector";
std::cerr << " dataset_save_path" << std::endl;
// std::cerr << " path_to_settings";
// std::cerr << " path_to_ros2bag_1";
// std::cerr << " (path_to_ros2bag_2 ... path_to_ros2bag_N) " << std::endl;
return 1;
}
}
', uri = "file:///home/localadmin/test/src/main.cpp", version = 0 } }}
[ERROR][2022-10-24 14:16:22] .../vim/lsp/rpc.lua:734 "rpc" "clangd" "stderr" "I[14:16:22.723] <-- initialized
I[14:16:22.723] unhandled notification initialized
I[14:16:22.723] <-- textDocument/didOpen
"
[ERROR][2022-10-24 14:16:22] .../vim/lsp/rpc.lua:734 "rpc" "clangd" "stderr" "I[14:16:22.724] Failed to find compilation database for /home/localadmin/test/src/main.cpp
I[14:16:22.724] Updating file /home/localadmin/test/src/main.cpp with command clangd fallback
[/home/localadmin/test/src]
/usr/lib/llvm-10/bin/clang /home/localadmin/test/src/main.cpp -fsyntax-only -resource-dir=/usr/lib/llvm-10/lib/clang/10.0.0
"
[ERROR][2022-10-24 14:16:22] .../vim/lsp/rpc.lua:734 "rpc" "clangd" "stderr" "I[14:16:22.994] --> textDocument/publishDiagnostics
"
[DEBUG][2022-10-24 14:16:22] .../vim/lsp/rpc.lua:388 "rpc.receive" { jsonrpc = "2.0", method = "textDocument/publishDiagnostics", params = { diagnostics = { { code = "pp_file_not_found", message = "'opencv2/opencv.hpp' file not found", range = { ["end"] = { character = 29, line = 1 }, start = { character = 9, line = 1 } }, relatedInformation = {}, severity = 1, source = "clang" } }, uri = "file:///home/localadmin/test/src/main.cpp" }}
[TRACE][2022-10-24 14:16:22] .../lua/vim/lsp.lua:1052 "notification" "textDocument/publishDiagnostics" { diagnostics = { { code = "pp_file_not_found", message = "'opencv2/opencv.hpp' file not found", range = { ["end"] = { character = 29, line = 1 }, start = { character = 9, line = 1 } }, relatedInformation = {}, severity = 1, source = "clang" } }, uri = "file:///home/localadmin/test/src/main.cpp"}
[TRACE][2022-10-24 14:16:22] ...lsp/handlers.lua:519 "default_handler" "textDocument/publishDiagnostics" { ctx = '{
client_id = 1,
method = "textDocument/publishDiagnostics"
}', result = { diagnostics = { { code = "pp_file_not_found", message = "'opencv2/opencv.hpp' file not found", range = { ["end"] = { character = 29, line = 1 }, start = { character = 9, line = 1 } }, relatedInformation = {}, severity = 1, source = "clang" } }, uri = "file:///home/localadmin/test/src/main.cpp" }}
[INFO][2022-10-24 14:16:29] .../lua/vim/lsp.lua:1814 "exit_handler" { { _on_attach = <function 1>, attached_buffers = { true }, cancel_request = <function 2>, commands = {}, config = { _on_attach = <function 3>, autostart = true, capabilities = { callHierarchy = { dynamicRegistration = false }, offsetEncoding = { "utf-8", "utf-16" }, textDocument = { codeAction = { codeActionLiteralSupport = { codeActionKind = { valueSet = { "", "Empty", "QuickFix", "Refactor", "RefactorExtract", "RefactorInline", "RefactorRewrite", "Source", "SourceOrganizeImports", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } } }, dataSupport = true, dynamicRegistration = false, isPreferredSupport = true, resolveSupport = { properties = { "edit" } } }, completion = { completionItem = { commitCharactersSupport = false, deprecatedSupport = false, documentationFormat = { "markdown", "plaintext" }, preselectSupport = false, snippetSupport = false }, completionItemKind = { valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } }, contextSupport = false, dynamicRegistration = false, editsNearCursor = true }, declaration = { linkSupport = true }, definition = { linkSupport = true }, documentHighlight = { dynamicRegistration = false }, documentSymbol = { dynamicRegistration = false, hierarchicalDocumentSymbolSupport = true, symbolKind = { valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } } }, hover = { contentFormat = { "markdown", "plaintext" }, dynamicRegistration = false }, implementation = { linkSupport = true }, publishDiagnostics = { relatedInformation = true, tagSupport = { valueSet = { 1, 2 } } }, references = { dynamicRegistration = false }, rename = { dynamicRegistration = false, prepareSupport = true }, signatureHelp = { dynamicRegistration = false, signatureInformation = { activeParameterSupport = true, documentationFormat = { "markdown", "plaintext" }, parameterInformation = { labelOffsetSupport = true } } }, synchronization = { didSave = true, dynamicRegistration = false, willSave = false, willSaveWaitUntil = false }, typeDefinition = { linkSupport = true } }, window = { showDocument = { support = false }, showMessage = { messageActionItem = { additionalPropertiesSupport = false } }, workDoneProgress = true }, workspace = { applyEdit = true, configuration = true, symbol = { dynamicRegistration = false, hierarchicalWorkspaceSymbolSupport = true, symbolKind = { valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } } }, workspaceEdit = { resourceOperations = { "rename", "create", "delete" } }, workspaceFolders = true } }, cmd = { "clangd", "--background-index", "--suggest-missing-includes" }, cmd_cwd = "/home/localadmin/test", filetypes = { "c", "cpp", "objc", "objcpp" }, flags = {}, get_language_id = <function 4>, handlers = <1>{}, init_options = vim.empty_dict(), log_level = 2, message_level = 2, name = "clangd", on_attach = <function 5>, on_exit = <function 6>, on_init = <function 7>, root_dir = "/home/localadmin/test", settings = vim.empty_dict(), single_file_support = true, workspace_folders = <2>{ { name = "/home/localadmin/test", uri = "file:///home/localadmin/test" } }, <metatable> = <3>{ __tostring = <function 8> } }, handlers = <table 1>, id = 1, initialized = true, is_stopped = <function 9>, messages = { messages = {}, name = "clangd", progress = {}, status = {} }, name = "clangd", notify = <function 10>, offset_encoding = "utf-8", request = <function 11>, request_sync = <function 12>, requests = {}, rpc = { is_closing = <function 13>, notify = <function 14>, request = <function 15>, terminate = <function 16> }, server_capabilities = { codeActionProvider = { codeActionKinds = { "quickfix", "refactor", "info" } }, completionProvider = { resolveProvider = false, triggerCharacters = { ".", ">", ":" } }, declarationProvider = true, definitionProvider = true, documentFormattingProvider = true, documentHighlightProvider = true, documentLinkProvider = { resolveProvider = false }, documentOnTypeFormattingProvider = { firstTriggerCharacter = "
", moreTriggerCharacter = {} }, documentRangeFormattingProvider = true, documentSymbolProvider = true, executeCommandProvider = { commands = { "clangd.applyFix", "clangd.applyTweak" } }, hoverProvider = true, referencesProvider = true, renameProvider = { prepareProvider = true }, selectionRangeProvider = true, signatureHelpProvider = { triggerCharacters = { "(", "," } }, textDocumentSync = { change = 2, openClose = true, save = { includeText = false }, willSave = false, willSaveWaitUntil = false }, typeHierarchyProvider = true, workspaceSymbolProvider = true }, stop = <function 17>, supports_method = <function 18>, workspaceFolders = <table 2>, workspace_did_change_configuration = <function 19>, workspace_folders = <table 2>, <metatable> = { __index = <function 20> } } }
[DEBUG][2022-10-24 14:16:29] .../vim/lsp/rpc.lua:285 "rpc.send" { id = 2, jsonrpc = "2.0", method = "shutdown"}
[ERROR][2022-10-24 14:16:30] .../vim/lsp/rpc.lua:734 "rpc" "clangd" "stderr" "I[14:16:30.000] <-- shutdown(2)
I[14:16:30.000] --> reply:shutdown(2) 0 ms
"
[DEBUG][2022-10-24 14:16:30] .../vim/lsp/rpc.lua:388 "rpc.receive" { id = 2, jsonrpc = "2.0"}
[DEBUG][2022-10-24 14:16:30] .../vim/lsp/rpc.lua:285 "rpc.send" { jsonrpc = "2.0", method = "exit"}
[START][2022-10-24 14:18:47] LSP logging initiated
[INFO][2022-10-24 14:18:47] .../lua/vim/lsp.lua:1814 "exit_handler" {}

Given the file /home/localuser/Projects/SLAM3/Examples/Stereo-Inertial/stereo_inertial_bag.cc, the places clangd will look are:
/home/localuser/Projects/SLAM3/Examples/Stereo-Inertial/compile_commands.json
/home/localuser/Projects/SLAM3/Examples/Stereo-Inertial/build/compile_commands.json
/home/localuser/Projects/SLAM3/Examples/compile_commands.json
/home/localuser/Projects/SLAM3/Examples/build/compile_commands.json
/home/localuser/Projects/SLAM3/compile_commands.json
/home/localuser/Projects/SLAM3/build/compile_commands.json
/home/localuser/Projects/compile_commands.json
/home/localuser/Projects/build/compile_commands.json
etc.
It does not look at /home/localuser/SLAM3/MyProject/build because your source file is not in MyProject.

Related

Invisible chart area during print and in exported PDF file in spreadsheet created by service account with Google Sheets API (Node.js) in shared folder

I'm creating a spreadsheet in Node.js environment in shared folder using service account with Google Sheets API v.4 in few steps:
Create spreadsheet itself in shared folder with "Can Edit" permission for service account.
Inserting some data and performing some text formats using spreadsheet ID received as callback from previous step.
Inserting chart using as income data the data inserted in prevoius step.
As the result I have a spreadsheet with expected result (text data and horizontal bar chart on same sheet). But when I'm trying to send it on printer, or download as PDF-file - chart area becomes completely invisible. I didn't find any option in official documentation about possible chart visibility during printing or something like this. And when I'm replacing this created chart with manually created one - everything is ok, I can print it and export to PDF.
So, what is the problem? Am I missing something? Or it's some bug?
index.js
const fs = require('fs');
const { google } = require('googleapis');
const express = require('express');
const bodyParser = require("body-parser");
const app = express();
const PORT = 3000;
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.listen(PORT, () => {
console.log(`Server started at http://localhost:${PORT}`)
})
const SCOPES = ['https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/spreadsheets'];
const FOLDER_ID = '1xG3xHhrucB4AGLmnd8T2TmCyqhmPux5Q';
var timeStamp = new Date().getTime();
console.log(`timeStamp at startup = ${timeStamp}`);
const auth = new google.auth.GoogleAuth({
keyFile: 'credentials.json',
scopes: SCOPES
});
process.env.HTTPS_PROXY = 'http://10.5.0.20:3128';
const sheets = google.sheets({
version: 'v4',
auth: auth,
proxy: 'http://10.5.0.20:3128'
});
const drive = google.drive({
version: 'v3',
auth: auth,
proxy: 'http://10.5.0.20:3128'
});
function createFileName() {
const now = new Date();
let date = String(now.toISOString().slice(0, 10));
let hours = String(now.getHours()).padStart(2, "0");
let minutes = String(now.getMinutes()).padStart(2, "0");
let seconds = String(now.getSeconds()).padStart(2, "0");
let humanDate = date.replaceAll('-', '.');
humanDate = `${humanDate}_${hours}-${minutes}-${seconds}`;
return humanDate;
}
async function saveFileLocally(filePath, data) {
fs.writeFile(filePath, JSON.stringify(data), error => {
if (error) {
console.error(error);
return;
}
});
return true;
}
app.get("/check", (req, res) => {
res.send('server is online...');
});
app.post("/motivation", async (req, res) => {
if(!req.body) return res.sendStatus(400);
try {
const prizv = req.body.prizv;
const name = req.body.name;
const father = req.body.father;
const sex = req.body.sex;
const age = req.body.age;
const factors = req.body.factors;
const testName = 'motivation';
const clientData = { prizv: prizv, name: name, father: father, sex: sex, age: age, factors: factors, testName: testName };
const fileName = `${createFileName()}_${prizv}`;
const filePath = `files/${testName}/${fileName}.txt`;
const isSaved = await saveFileLocally(filePath, clientData);
if (isSaved) {
console.log(`file is saved locally....`);
const sheetID = await createSheetToGoogleDIsk(clientData, fileName);
res.send(sheetID);
}
} catch (error) {
console.log(error)
}
});
async function createSheetToGoogleDIsk(clientData, fileName) {
const file = fileName;
var sheetsMetadata = {
name: file,
mimeType: 'application/vnd.google-apps.spreadsheet',
parents: [FOLDER_ID]
};
const res2 = drive.files.create({
resource: sheetsMetadata,
fields: 'id'
}, function (err, file) {
if (err) {
console.error(err);
} else {
console.log('SheetID: ', file.data.id);
const gSheetID = file.data.id;
pasteDataToGoogleSheet(clientData, gSheetID);
insertChartToGoogleSheet(gSheetID);
return file.data.id;
}
});
}
async function insertChartToGoogleSheet(spreadsheetId) {
spreadsheetId = spreadsheetId;
let requests = [];
// set font size for whole Sheet as 14
requests.push({
"repeatCell": {
"range": {
"sheetId": 0,
"startRowIndex": 0,
"endRowIndex": 100,
},
"cell": {
"userEnteredFormat": {
"textFormat": {
"fontSize": 13,
},
},
},
"fields": "userEnteredFormat.textFormat.fontSize"
},
});
// set header text format as Bold and 18 pt
requests.push({
"repeatCell": {
"range": {
"sheetId": 0,
"startRowIndex": 0,
"endRowIndex": 2,
},
"cell": {
"userEnteredFormat": {
"textFormat": {
"fontSize": 18,
"bold": true
},
},
},
"fields": "userEnteredFormat(textFormat)"
},
});
// set subheader text format as Bold and 15 pt
requests.push({
"repeatCell": {
"range": {
"sheetId": 0,
"startRowIndex": 3,
"endRowIndex": 4,
},
"cell": {
"userEnteredFormat": {
"textFormat": {
"fontSize": 15,
"bold": true
},
},
},
"fields": "userEnteredFormat(textFormat)"
},
});
// set client data as Bold
requests.push({
"repeatCell": {
"range": {
"sheetId": 0,
"startRowIndex": 5,
"endRowIndex": 10,
"startColumnIndex": 3,
"endColumnIndex": 5
},
"cell": {
"userEnteredFormat": {
"textFormat": {
"fontSize": 13,
"bold": true
},
},
},
"fields": "userEnteredFormat(textFormat)"
},
});
// set 1st column width as 20px
requests.push({
"updateDimensionProperties": {
"range": {
"sheetId": 0,
"dimension": "COLUMNS",
"startIndex": 0,
"endIndex": 1
},
"properties": {
"pixelSize": 20
},
"fields": "pixelSize"
}
});
// set 4st column width as 150px
requests.push({
"updateDimensionProperties": {
"range": {
"sheetId": 0,
"dimension": "COLUMNS",
"startIndex": 3,
"endIndex": 4
},
"properties": {
"pixelSize": 150
},
"fields": "pixelSize"
}
});
// set bold factors Values
requests.push({
"repeatCell": {
"range": {
"sheetId": 0,
"startRowIndex": 33,
"endRowIndex": 45,
"startColumnIndex": 4,
"endColumnIndex": 5
},
"cell": {
"userEnteredFormat": {
"textFormat": {
"fontSize": 13,
"bold": true
},
},
},
"fields": "userEnteredFormat(textFormat)"
},
});
requests.push({
"addChart": {
"chart": {
"chartId": 1,
"spec": {
"titleTextFormat": {
},
"basicChart": {
"chartType": "BAR",
"axis": [
{
"position": "BOTTOM_AXIS",
},
{
"position": "LEFT_AXIS",
}
],
"domains": [
{
"domain": {
"sourceRange": {
"sources": [
{
"sheetId": 0,
"startRowIndex": 33,
"endRowIndex": 45,
"startColumnIndex": 1,
"endColumnIndex": 2
}
]
},
},
}
],
"series": [
{
"series": {
"sourceRange": {
"sources": [
{
"sheetId": 0,
"startRowIndex": 33,
"endRowIndex": 45,
"startColumnIndex": 4,
"endColumnIndex": 5
}
]
}
},
"targetAxis": "BOTTOM_AXIS"
}
],
},
},
"position": {
"overlayPosition": {
"anchorCell": {
"sheetId": 0,
"rowIndex": 11,
"columnIndex": 1
},
"offsetXPixels": 0,
"offsetYPixels": -7,
"widthPixels": 800,
"heightPixels": 450
},
},
"border": {
"color": {
"red": 1,
"green": 1,
"blue": 1,
"alpha": 0
},
}
}
}
});
const batchUpdateRequest = { requests };
sheets.spreadsheets.batchUpdate({
spreadsheetId,
resource: batchUpdateRequest,
}, (err, result) => {
if (err) {
// Handle error
console.log(err);
return false
} else {
console.log(`${result.updatedCells} chart inserted`);
return spreadsheetId
}
});
}
async function pasteDataToGoogleSheet(clientData, sheetId) {
ecxelID = sheetId;
let data1 = [
["Тест «Мотиваційний особистісний профіль»"], [""], ["Результати тестування"], [""], ["Прізвище"], ["Імя"], ["По-батькові"], ["Вік"], ["Стать"]
];
let data2 = [
[clientData.prizv], [clientData.name], [clientData.father], [clientData.age], [clientData.sex]
];
let factorsLabels1_6 = [
["1. Матеріальна винагорода:"], ["2. Комфортні умови:"], ["3. Структурованість роботи:"], ["4. Соціальні контакти:"], ["5. Довірливі стосунки:"], ["6. Визнання:"]
];
let factors1_6 = [
[clientData.factors.factor1], [clientData.factors.factor2], [clientData.factors.factor3], [clientData.factors.factor4], [clientData.factors.factor5], [clientData.factors.factor6]
];
let factorsLabels7_12 = [
["7. Досягнення мети:"], ["8. Влада і вплив:"], ["9. Відсутність рутини:"], ["10. Креативність:"], ["11. Самовдосконалення і розвиток:"], ["12. Цікава і корисна діяльність:"]
];
let factors7_12 = [
[clientData.factors.factor7], [clientData.factors.factor8], [clientData.factors.factor9], [clientData.factors.factor10], [clientData.factors.factor11], [clientData.factors.factor12]
];
const data = [{
range: "B2:B10",
values: data1,
},
{
range: "D6:D10",
values: data2,
},
{
range: "B34:B39",
values: factorsLabels1_6,
},
{
range: "E34:E39",
values: factors1_6,
},
{
range: "B40:B45",
values: factorsLabels7_12,
},
{
range: "E40:E45",
values: factors7_12,
}
];
const resource = {
data,
valueInputOption: 'RAW',
};
sheets.spreadsheets.values.batchUpdate({
spreadsheetId: ecxelID,
resource: resource,
}, (err, result) => {
if (err) {
// Handle error
console.log(err);
return false
} else {
console.log(`${result.updatedCells} cells data inserted`);
return spreadsheetId;
}
});
}
I could confirm your situation. In this case, how about the following modification?
From:
"offsetXPixels": 0,
"offsetYPixels": -7,
"widthPixels": 800,
"heightPixels": 450
To:
"offsetXPixels": 0,
"offsetYPixels": 0, // Modified
"widthPixels": 800,
"heightPixels": 450
or
"widthPixels": 800,
"heightPixels": 450
When the values of offsetXPixels and offsetYPixels are the negative values, it was found that such an issue occurs.
When the values of offsetXPixels and offsetYPixels are 0, these values are not required to be included because of the default value.
Note:
When I tested the above modification, I could confirm that your issue could be removed.
Reference:
EmbeddedObjectPosition

MongoDB GridFSBucket upload stream doesn't return length of base64 image stream

I'm refactoring my team code to remove Deprecation Warnings from MongoDB.
I removed gridfs-stream library and I'm using GridFSBucket instead
But there is a problem: upload stream using GridFSBucket doesn't return the length of base64 image, instead it returns 0. This breaks one of the tests in our code.
This is the code using GridFSBucket:
function getGrid() {
return new mongoose.mongo.GridFSBucket(conn.db);
}
module.exports.store = function(id, contentType, metadata, stream, options, callback) {
... // unrelated things
var strMongoId = mongoId.toHexString(); // http://stackoverflow.com/a/27176168
var opts = {
contentType: contentType,
metadata: metadata
};
options = options || {};
if (options.filename) {
opts.filename = options.filename;
}
if (options.chunk_size) {
var size = parseInt(options.chunk_size, 10);
if (!isNaN(size) && size > 0 && size < 255) {
opts.chunkSizeBytes = chunk_size * size;
}
}
var gfs = getGrid();
var writeStream = gfs.openUploadStreamWithId(strMongoId, opts.filename, opts);
writeStream.on('finish', function(file) {
console.log(file) // <== Notice the log for this line below
return callback(null, file);
});
writeStream.on('error', function(err) {
return callback(err);
});
stream.pipe(writeStream);
};
The result for console.log(file) is:
{
"_id": "5ea7a3ffbc7dd36e7df4561e",
"length": 0, // <== Notice length is 0 here
"chunkSize": 10240,
"uploadDate": "2020-04-28T03:33:19.734Z",
"filename": "default_profile.png",
"md5": "d41d8cd98f00b204e9800998ecf8427e",
"contentType": "image/png",
"metadata": {
"name": "default_profile.png",
"creator": {
"objectType": "user",
"id": "5ea7a3febc7dd36e7df4560a"
}
}
}
This is the old code using gridfs-stream:
var Grid = require('gridfs-stream');
...
function getGrid() {
return new Grid(mongoose.connection.db, mongoose.mongo);
}
module.exports.store = function(id, contentType, metadata, stream, options, callback) {
... // unrelated things
var strMongoId = mongoId.toHexString(); // http://stackoverflow.com/a/27176168
var opts = {
_id: strMongoId,
mode: 'w',
content_type: contentType
};
options = options || {};
if (options.filename) {
opts.filename = options.filename;
}
if (options.chunk_size) {
var size = parseInt(options.chunk_size, 10);
if (!isNaN(size) && size > 0 && size < 255) {
opts.chunk_size = chunk_size * size;
}
}
opts.metadata = metadata;
var gfs = getGrid();
var writeStream = gfs.createWriteStream(opts);
writeStream.on('close', function(file) {
console.log(file) // <== Notice the log for this line below
return callback(null, file);
});
writeStream.on('error', function(err) {
return callback(err);
});
stream.pipe(writeStream);
};
And here is the result of console.log(file):
{
"_id": "5ea7a43a5d6eea73e0a3c8b1",
"filename": "default_profile.png",
"contentType": "image/png",
"length": 634, // <== We have the length here
"chunkSize": 10240,
"uploadDate": "2020-04-28T03:34:18.069Z",
"metadata": {
"name": "default_profile.png",
"creator": {
"objectType": "user",
"id": "5ea7a4395d6eea73e0a3c89d"
}
},
"md5": "c37659eb6a9e741656a8d0348765c668"
}
So how can I get the length using GridFSBucket?
Thank you!
UPDATE:
This is the log of variable stream in both cases:
{
"contentType": "image/png",
"fileName": "default_profile.png",
"transferEncoding": "base64",
"contentDisposition": "attachment",
"generatedFileName": "default_profile.png",
"contentId": "216d9aab57544410901f8ba7981e63aa#mailparser",
"stream": {
"_events": {},
"_eventsCount": 0,
"writable": true,
"checksum": {
"_handle": {},
"writable": true,
"readable": true
},
"length": 0,
"current": ""
}
}

Terraform eks module - workers custom tags

I want to have 2 worker groups, each with custom tag.
For example, if I use this template - https://github.com/terraform-aws-modules/terraform-aws-eks/blob/v4.0.2/examples/basic/main.tf
worker_groups = [
{
name = "worker-group-1"
....
//here - what I want to have
tags = {selector=wg1}
},
{
name = "worker-group-2"
....
//here - what I want to have
tags = {selector=wg2}
},
I see the input variables in https://github.com/terraform-aws-modules/terraform-aws-eks/blob/v4.0.2/variables.tf , lines 115-122
and template - https://github.com/terraform-aws-modules/terraform-aws-eks/blob/v4.0.2/workers.tf , lines 19-29,
but I can't understand how to properly configure them to get custom tags on workers.
The current version has changed slightly:
worker_groups = [
{
name = "worker-group-1"
....
tags = [
{
key = "k1"
value = "v1"
propagate_at_launch = true
},
{
key = "k2"
value = "v2"
propagate_at_launch = true
}
]
}]
I've found where it was implemented and the example how to use it:
worker_groups = [
{
name = "worker-group-1"
....
},
{
name = "worker-group-2"
....
},
]
// and here comes the tags block
worker_group_tags = {
worker-group-1 = [
{
key = "k1"
value = "v1"
key = "k2"
value = "v2"
propagate_at_launch = true
},
],
worker-group-2 = [
{
key = "k3"
value = "v3"
key = "k4"
value = "v4"
propagate_at_launch = true
},
],
}

Useing amChart serias

We have created something like this, and now I wont to add some periods to my chart codepen. but the code that I wrote doesn't work. Thank you
am4core.useTheme(am4themes_animated);
let items = [
{
"X": 1,
"Y": 2,
"code": "ExecDate",
"date": "May 06, 2010",
"enabled": true,
"name": "Execution Date",
"refTxt": null,
"refX": null
},
{
"X": 1,
"Y": -1,
"code": "EffDate",
"date": "May 07, 2010",
"enabled": true,
"name": "Effective Date",
"refTxt": null,
"refX": null
},
....
];
let periods = [
{
"Xend": "May 08, 2010",
"Xstart": "May 07, 2010",
"Y": 1,
"code": "PunchPeriod",
"name": "Punch List Completion Period"
},
...
];
Please help me
I already writed correct code
am4core.useTheme(am4themes_animated);
let items = [
{
"X": 1,
"Y": 2,
"code": "ExecDate",
"date": "May 06, 2010",
"enabled": true,
"name": "Execution Date",
"refTxt": null,
"refX": null
},
{
"X": 1,
"Y": -1,
"code": "EffDate",
"date": "May 07, 2010",
"enabled": true,
"name": "Effective Date",
"refTxt": null,
"refX": null
},
];
let chart = am4core.create("chart-am", am4charts.XYChart);
chart.data = items;
chart.dateFormatter.inputDateFormat = "MMM d, yyyy";
chart.maskBullets = false;
chart.paddingRight = 30;
// Create axes
let dateAxis = chart.xAxes.push(new am4charts.DateAxis());
dateAxis.dateFormatter.dateFormat = "MMM d, yyyy";
dateAxis.renderer.tooltipLocation = 0;
dateAxis.extraMin = 0.1;
dateAxis.extraMax = 0.1;
let valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.title.text = "Transaction Volume";
valueAxis.renderer.baseGrid.disabled = true;
valueAxis.renderer.grid.template.strokeOpacity = 0.07;
// Create series
let series = chart.series.push(new am4charts.ColumnSeries());
series.dataFields.valueY = "Y";
series.dataFields.dateX = "date";
series.tooltip.pointerOrientation = "vertical";
series.columns.template.fill = am4core.color("#000")
// green label
let label = series.columns.template.createChild(am4core.Label);
label.text = "{name}";
label.align = "left";
label.valign = "top";
label.zIndex = 2;
label.fill = am4core.color("#000");
label.background.fill = am4core.color("green");
label.background.opacity = 0.6
label.strokeWidth = 0;
label.width = 100
label.height = 70
label.wrap = true
label.textValign = 'middle'
//label.textAlign = 'center'
label.fontSize = 11
label.bbox.y = -100
let columnTemplate = series.columns.template;
columnTemplate.layout = "horizontal";
columnTemplate.width = 3;
columnTemplate.column.tooltipText = "Series: {name}\nDate: {categoryX}\nCount: {valueY}";
columnTemplate.column.tooltipY = 0;
columnTemplate.column.cornerRadiusTopLeft = 0;
columnTemplate.column.cornerRadiusTopRight = 0;
columnTemplate.strokeOpacity = 0;
columnTemplate.adapter.add("fill", (fill, target) => {
let color = chart.colors.getIndex(target.dataItem.index * 3);
return color;
});
let periods = [
{
"Xstart": "May 07, 2010",
"Xend": "May 08, 2010",
"openY": -1.5,
"Y": -2,
"code": "PunchPeriod",
"name": "Punch List Completion Period"
},
{
"Xstart": "May 10, 2010", // was may 12
"Xend": "May 12, 2010", // was may 10
"openY": -2.5,
"Y": -3,
"code": "TitlePeriod",
"name": "Title Transfer Period"
},
{
"Xstart": "May 13, 2010", // was may 18
"Xend": "May 18, 2010", // was may 13
"openY": -3.5,
"Y": -4,
"code": "ConstPeriod",
"name": "Construction Period"
}
];
let periodSeries = chart.series.push(new am4charts.ColumnSeries());
periodSeries.data = periods;
periodSeries.dataFields.openValueY = "openY";
periodSeries.dataFields.valueY = "Y";
periodSeries.dataFields.openDateX = "Xstart";
periodSeries.dataFields.dateX = "Xend";
periodSeries.columns.template.tooltipText = "{name}: {openDateX} - {dateX}";
periodSeries.columns.template.propertyFields.fill = "color";
periodSeries.columns.template.propertyFields.stroke = "color";
periodSeries.columns.template.strokeOpacity = 1;
let periodLabel = periodSeries.columns.template.createChild(am4core.Label);
periodLabel.text = "{name}";
periodLabel.align = "center";
periodLabel.color = "color";
label.align = "center";
periodLabel.valign = "top";
periodLabel.zIndex = 500;
periodLabel.fill = am4core.color("#000");
periodLabel.background.fill = am4core.color("red");
periodLabel.background.opacity = 0.6
periodLabel.strokeWidth = 0;
periodLabel.width = 100
periodLabel.height = 70
periodLabel.wrap = true
periodLabel.textValign = 'middle'
periodLabel.textAlign = 'center'
periodLabel.fontSize = 11
periodLabel.bbox.y = -100
chart.scrollbarX = new am4core.Scrollbar();

sencha touch: real time chart

i am using sencha touch to show a chart and add data to store of chart dynamically.but when i add data to store, my chart does not update result.
this is code of my chart:
Ext.define('MyApp.view.MyLineChart1', {
extend: 'Ext.chart.CartesianChart',
requires: [
'Ext.chart.axis.Category',
'Ext.chart.axis.Numeric',
'Ext.chart.series.Line'
],
config: {
itemId: 'xy',
store: 'MyStore',
colors: [
'#115fa6',
'#94ae0a',
'#a61120',
'#ff8809',
'#ffd13e',
'#a61187',
'#24ad9a',
'#7c7474',
'#a66111'
],
axes: [
{
type: 'category',
fields: [
'x'
],
maximum: 5,
minimum: 0
},
{
type: 'numeric',
fields: [
'y'
],
grid: {
odd: {
fill: '#e8e8e8'
}
},
position: 'left'
}
],
series: [
{
type: 'line',
colors: 'rgba(0,200,0,0.3)',
style: {
smooth: true,
stroke: 'rgb(0,200,0)',
},
xField: 'x',
yField: 'y'
}
],
listeners: [
{
fn: 'onChartShow',
event: 'show',
order: 'after'
}
]
},
onChartShow: function(component, eOpts) {
var TaskRunner = Ext.create("MyApp.controller.TaskRunner");
chart = Ext.ComponentQuery.query("#xy")[0];
store = chart.getStore();
chart.animationSuspended = true;
chart.update();
store.removeAll();
this.timeChartTask = TaskRunner.start({
run: this.update_chart,
interval: 1000,
repeat: 10,
scope: this
});
},
update_chart: function(chart) {
var me = this;
chart = Ext.ComponentQuery.query("#xy")[0];
store = chart.getStore();
count = store.getCount();
xAxis = chart.getAxes()[0];
visibleRange = 10000;
second = 1000;
console.log(xAxis.getMinimum());
if (count > 0) {
lastRecord = store.getAt(count - 1);
xValue = lastRecord.get('x') + second;
if (xValue - me.startTime > visibleRange) {
me.startTime = xValue - visibleRange;
xAxis.setMinimum(this.startTime);
xAxis.setMaximum(xValue);
console.log("count >0");
}
store.add({
x: xValue,
y: me.getNextValue()
});
// store.load();
chart.redraw();
} else {
chart.animationSuspended = true;
me.startTime = Math.floor(Ext.Date.now() / second) * second;
xAxis.setMinimum(me.startTime);
xAxis.setMaximum(me.startTime + visibleRange);
store.add({
x: this.startTime,
y: me.getNextValue()
});
chart.animationSuspended = false;
// store.load();
chart.redraw();
console.log("count < 0");
}
},
getNextValue: function(previousValue) {
var delta = Math.random()*4 - 2;
if (Ext.isNumber(previousValue)) {
return Ext.Number.constrain(previousValue + delta, -2, 2);
}
return Math.random()*4 - 2;
}
});
this is my store:
Ext.define('MyApp.store.MyStore', {
extend: 'Ext.data.Store',
requires: [
'MyApp.model.MyModel1'
],
config: {
model: 'MyApp.model.MyModel1',
storeId: 'MyStore'
}
});
and this is my model:
Ext.define('MyApp.model.MyModel1', {
extend: 'Ext.data.Model',
requires: [
'Ext.data.Field'
],
config: {
fields: [
{
name: 'x'
},
{
name: 'y'
}
]
}
});
If you want set data to store use this code:
var store = Ext.getStore('MyStore');
store.load(function () {
var store = Ext.getStore('MyStore');
store.removeAll();
store.add({
x: xValue,
y: me.getNextValue()
});
store.sync();
});