updates
This commit is contained in:
parent
8ba8fc98ca
commit
e2ee24b57a
13 changed files with 238 additions and 70 deletions
|
|
@ -12,14 +12,14 @@ in {
|
||||||
enable = mkBoolOpt false "Enable Kitty Term";
|
enable = mkBoolOpt false "Enable Kitty Term";
|
||||||
|
|
||||||
fonts = {
|
fonts = {
|
||||||
# normal = mkStringOpt "ZedMono Nerd Font Mono Bold" "Normal Font";
|
normal = mkStringOpt "JetBrainsMonoNL Nerd Font Mono Bold" "Normal Font";
|
||||||
# bold = mkStringOpt "ZedMono Nerd Font Mono ExtraBold" "Bold Font";
|
bold = mkStringOpt "JetBrainsMonoNL Nerd Font Mono ExtraBold" "Bold Font";
|
||||||
# italic = mkStringOpt "ZedMono Nerd Font Mono Bold Italic" "Italic Font";
|
italic = mkStringOpt "JetBrainsMonoNL Nerd Font Mono Bold Italic" "Italic Font";
|
||||||
# bold_italic = mkStringOpt "ZedMono Nerd Font Mono ExtraBold Italic" "Bold Italic Font";
|
bold_italic = mkStringOpt "JetBrainsMonoNL Nerd Font Mono ExtraBold Italic" "Bold Italic Font";
|
||||||
normal = mkStringOpt "Iosevka Bold" "Normal Font";
|
# normal = mkStringOpt "Iosevka Bold" "Normal Font";
|
||||||
bold = mkStringOpt "Iosevka ExtraBold" "Bold Font";
|
# bold = mkStringOpt "Iosevka ExtraBold" "Bold Font";
|
||||||
italic = mkStringOpt "Iosevka Bold Italic" "Italic Font";
|
# italic = mkStringOpt "Iosevka Bold Italic" "Italic Font";
|
||||||
bold_italic = mkStringOpt "Iosevka ExtraBold Italic" "Bold Italic Font";
|
# bold_italic = mkStringOpt "Iosevka ExtraBold Italic" "Bold Italic Font";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
"lazyvim.plugins.extras.lang.tailwind",
|
"lazyvim.plugins.extras.lang.tailwind",
|
||||||
"lazyvim.plugins.extras.lang.elixir",
|
"lazyvim.plugins.extras.lang.elixir",
|
||||||
"lazyvim.plugins.extras.lang.tex",
|
"lazyvim.plugins.extras.lang.tex",
|
||||||
|
"lazyvim.plugins.extras.lang.go",
|
||||||
"lazyvim.plugins.extras.lang.typescript",
|
"lazyvim.plugins.extras.lang.typescript",
|
||||||
"lazyvim.plugins.extras.test.core",
|
"lazyvim.plugins.extras.test.core",
|
||||||
"lazyvim.plugins.extras.util.dot",
|
"lazyvim.plugins.extras.util.dot",
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,121 @@
|
||||||
-- Keymaps are automatically loaded on the VeryLazy event
|
-- Function to get the visual selection
|
||||||
-- Default keymaps that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/keymaps.lua
|
local function get_visual_selection()
|
||||||
-- Add any additional keymaps here
|
-- Get the current buffer number (0 means current buffer)
|
||||||
|
local bufnr = 0
|
||||||
|
|
||||||
|
-- Get the total number of lines in the buffer
|
||||||
|
local line_count = vim.api.nvim_buf_line_count(bufnr)
|
||||||
|
|
||||||
|
-- Get all lines from the buffer (0-based index, end is exclusive)
|
||||||
|
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, line_count, false)
|
||||||
|
|
||||||
|
-- Get the file name
|
||||||
|
local file_name = vim.fn.expand("%:p")
|
||||||
|
|
||||||
|
-- Create the file info description
|
||||||
|
local file_info = string.format("File: %s (%d lines)", file_name, line_count)
|
||||||
|
|
||||||
|
-- Convert the lines into a single string
|
||||||
|
local file_contents = table.concat(lines, "\n")
|
||||||
|
|
||||||
|
-- Return both the file contents and the file info
|
||||||
|
return file_contents, file_info
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Function to parse JSON response and get gist URL
|
||||||
|
local function handle_response(response)
|
||||||
|
-- Parse the JSON response
|
||||||
|
local ok, decoded = pcall(vim.fn.json_decode, response)
|
||||||
|
if not ok then
|
||||||
|
vim.api.nvim_echo({ {
|
||||||
|
"Failed to parse response: " .. decoded,
|
||||||
|
"ErrorMsg",
|
||||||
|
} }, true, {})
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if we have the expected data structure
|
||||||
|
if not (decoded and decoded.data and decoded.data.id) then
|
||||||
|
vim.api.nvim_echo({ {
|
||||||
|
"Invalid response format",
|
||||||
|
"ErrorMsg",
|
||||||
|
} }, true, {})
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Construct the URL
|
||||||
|
return string.format("https://zoeys.computer/gists/%s", decoded.data.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Function to create gist
|
||||||
|
local function create_gist()
|
||||||
|
-- Get the selected code and line range
|
||||||
|
local selected_code, line_range = get_visual_selection()
|
||||||
|
|
||||||
|
-- Check if we got any code
|
||||||
|
if selected_code == "" then
|
||||||
|
vim.api.nvim_echo({ {
|
||||||
|
"No text selected",
|
||||||
|
"ErrorMsg",
|
||||||
|
} }, true, {})
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get the current file name with extension
|
||||||
|
local file_name = vim.fn.expand("%:t")
|
||||||
|
if file_name == "" then
|
||||||
|
file_name = "untitled." .. vim.bo.filetype
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create the payload table first
|
||||||
|
local payload = {
|
||||||
|
title = file_name,
|
||||||
|
desc = line_range,
|
||||||
|
code = selected_code,
|
||||||
|
lang = vim.bo.filetype,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Convert to JSON string
|
||||||
|
local json_data = vim.fn.json_encode(payload)
|
||||||
|
|
||||||
|
-- Create a temporary file for the JSON payload
|
||||||
|
local temp_file = os.tmpname()
|
||||||
|
local f = io.open(temp_file, "w")
|
||||||
|
f:write(json_data)
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
-- Construct and execute the curl command
|
||||||
|
local cmd = string.format(
|
||||||
|
[[
|
||||||
|
curl -s -X POST \
|
||||||
|
https://zoeys.computer/api/gists/create \
|
||||||
|
-H "Accept: application/json" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-H "Authorization: Bearer Z4MYrYtJUb3Y8VvJynkWAw9eBVU3kvvW9gQ50--hROw" \
|
||||||
|
-d @%s
|
||||||
|
]],
|
||||||
|
temp_file
|
||||||
|
)
|
||||||
|
|
||||||
|
-- Execute the command and get the response
|
||||||
|
local response = vim.fn.system(cmd)
|
||||||
|
|
||||||
|
-- Clean up the temporary file
|
||||||
|
os.remove(temp_file)
|
||||||
|
|
||||||
|
-- Parse response and get URL
|
||||||
|
local url = handle_response(response)
|
||||||
|
if url then
|
||||||
|
-- Copy URL to system clipboard
|
||||||
|
vim.fn.setreg("+", url)
|
||||||
|
|
||||||
|
-- Show success message
|
||||||
|
vim.api.nvim_echo({ {
|
||||||
|
"Gist created! URL copied to clipboard: " .. url,
|
||||||
|
"Normal",
|
||||||
|
} }, true, {})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set up the keybinding (you can modify this to your preferred key combination)
|
||||||
|
vim.keymap.set("n", "<leader>zc", create_gist, { noremap = true, silent = true, expr = true })
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
|
function confirm(opts)
|
||||||
|
local cmp = require("blink.cmp")
|
||||||
|
opts = vim.tbl_extend("force", { select = true }, opts or {})
|
||||||
|
return function(fallback) end
|
||||||
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
{
|
{
|
||||||
"LazyVim/LazyVim",
|
"LazyVim/LazyVim",
|
||||||
|
|
@ -5,6 +11,8 @@ return {
|
||||||
colorscheme = "catppuccin",
|
colorscheme = "catppuccin",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{ "nvim-lualine/lualine.nvim", enabled = false },
|
||||||
|
{ "echasnovski/mini.statusline", opts = {} },
|
||||||
{
|
{
|
||||||
"L3MON4D3/LuaSnip",
|
"L3MON4D3/LuaSnip",
|
||||||
dependencies = {
|
dependencies = {
|
||||||
|
|
@ -29,6 +37,18 @@ return {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ "hrsh7th/nvim-cmp", enabled = false },
|
{ "hrsh7th/nvim-cmp", enabled = false },
|
||||||
|
{
|
||||||
|
"lukas-reineke/indent-blankline.nvim",
|
||||||
|
main = "ibl",
|
||||||
|
tag = "v3.8.2",
|
||||||
|
---@module "ibl"
|
||||||
|
---@type ibl.config
|
||||||
|
-- opts = {
|
||||||
|
-- debounce = 100,
|
||||||
|
-- indent = { char = "|" },
|
||||||
|
-- whitespace = { highlight = "Whitespace", "NonText" },
|
||||||
|
-- },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"jake-stewart/force-cul.nvim",
|
"jake-stewart/force-cul.nvim",
|
||||||
config = function()
|
config = function()
|
||||||
|
|
@ -39,19 +59,49 @@ return {
|
||||||
"saghen/blink.cmp",
|
"saghen/blink.cmp",
|
||||||
lazy = false, -- lazy loading handled internally
|
lazy = false, -- lazy loading handled internally
|
||||||
-- optional: provides snippets for the snippet source
|
-- optional: provides snippets for the snippet source
|
||||||
dependencies = "rafamadriz/friendly-snippets",
|
dependencies = { "rafamadriz/friendly-snippets", "saghen/blink.compat" },
|
||||||
|
|
||||||
build = "cargo build --release",
|
build = "cargo build --release",
|
||||||
|
|
||||||
|
sources = {
|
||||||
|
completion = {
|
||||||
|
enabled_providers = { "lsp", "path", "snippets", "buffer", "dadbod", "crates" },
|
||||||
|
},
|
||||||
|
|
||||||
|
providers = {
|
||||||
|
dadbod = {
|
||||||
|
name = "vim-dadbod-completion",
|
||||||
|
module = "blink.compat",
|
||||||
|
opts = {},
|
||||||
|
},
|
||||||
|
crates = {
|
||||||
|
name = "crates",
|
||||||
|
module = "blink.compat",
|
||||||
|
opts = {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
---@module 'blink.cmp'
|
||||||
|
---@type blink.cmp.Config
|
||||||
opts = {
|
opts = {
|
||||||
keymap = {
|
keymap = {
|
||||||
show = "<C-S-space>",
|
["<C-b>"] = { "scroll_documentation_down", "fallback" },
|
||||||
accept = "<Enter>",
|
["<C-f>"] = { "scroll_documentation_up", "fallback" },
|
||||||
select_prev = { "<S-Tab>", "<C-j>", "<C-p>" },
|
["<C-p>"] = { "select_prev", "fallback" },
|
||||||
select_next = { "<C-Tab>", "<C-k>", "<C-n>" },
|
["<C-n>"] = { "select_next", "fallback" },
|
||||||
|
["<C-space>"] = { "show", "show_documentation", "hide_documentation" },
|
||||||
snippet_forward = "<Tab>",
|
["<CR>"] = {
|
||||||
snippet_backward = "<C-S-Tab>",
|
function(cmp)
|
||||||
|
if cmp.is_in_snippet() then
|
||||||
|
return cmp.accept()
|
||||||
|
else
|
||||||
|
return cmp.select_and_accept()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
"snippet_forward",
|
||||||
|
"fallback",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
windows = {
|
windows = {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ return {
|
||||||
"oysandvik94/curl.nvim",
|
"oysandvik94/curl.nvim",
|
||||||
cmd = { "CurlOpen" },
|
cmd = { "CurlOpen" },
|
||||||
keys = {
|
keys = {
|
||||||
{ "<leader>co", "<cmd>CurlOpen<cr>", desc = "Open Curl" },
|
{ "<leader>C", "<cmd>CurlOpen<cr>", desc = "Open Curl" },
|
||||||
},
|
},
|
||||||
dependencies = {
|
dependencies = {
|
||||||
"nvim-lua/plenary.nvim",
|
"nvim-lua/plenary.nvim",
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ in {
|
||||||
markdownlint-cli2
|
markdownlint-cli2
|
||||||
shfmt
|
shfmt
|
||||||
sqlfluff
|
sqlfluff
|
||||||
|
go
|
||||||
|
|
||||||
tailwindcss-language-server
|
tailwindcss-language-server
|
||||||
clang
|
clang
|
||||||
|
|
|
||||||
|
|
@ -97,8 +97,8 @@ in {
|
||||||
"${mod},mouse_up,workspace,e-1" # move to the previous ws
|
"${mod},mouse_up,workspace,e-1" # move to the previous ws
|
||||||
|
|
||||||
"${mod},X,exec, ags --toggle-window \"dashboard\""
|
"${mod},X,exec, ags --toggle-window \"dashboard\""
|
||||||
"${mod},Print,exec,grim -g \"$(slurp)\" - | wl-copy && wl-paste > ~/Pictures/Screenshots/Screenshot-$(date +%F_%T).png;"
|
"${mod},Print,exec,${lib.getExe pkgs.custom.sc}"
|
||||||
",Print,exec, grim - | wl-copy"
|
"${mod},Shift&Print,exec,${lib.getExe pkgs.wf-recorder} -g \"$(${lib.getExe pkgs.slurp})\" -f out.mp4"
|
||||||
"${modshift},O,exec,wl-ocr"
|
"${modshift},O,exec,wl-ocr"
|
||||||
|
|
||||||
"${mod},Period,exec, tofi-emoji"
|
"${mod},Period,exec, tofi-emoji"
|
||||||
|
|
|
||||||
|
|
@ -27,59 +27,27 @@ in {
|
||||||
rootCredentialsFile = config.age.secrets.minio.path;
|
rootCredentialsFile = config.age.secrets.minio.path;
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx.virtualHosts."s3.zoeys.computer" = {
|
services.nginx.virtualHosts."minio.zoeys.computer" = {
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
extraConfig = ''
|
|
||||||
# Allow special characters in headers
|
|
||||||
ignore_invalid_headers off;
|
|
||||||
# Allow any size file to be uploaded.
|
|
||||||
# Set to a value such as 1000m; to restrict file size to a specific value
|
|
||||||
client_max_body_size 0;
|
|
||||||
# Disable buffering
|
|
||||||
proxy_buffering off;
|
|
||||||
proxy_request_buffering off;
|
|
||||||
'';
|
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://localhost${config.services.minio.listenAddress}";
|
|
||||||
extraConfig = ''
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
|
|
||||||
proxy_connect_timeout 300;
|
|
||||||
# Default is HTTP/1, keepalive is only enabled in HTTP/1.1
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Connection "";
|
|
||||||
chunked_transfer_encoding off;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
locations."/minio/ui" = {
|
|
||||||
proxyPass = "http://localhost${config.services.minio.consoleAddress}";
|
proxyPass = "http://localhost${config.services.minio.consoleAddress}";
|
||||||
|
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
rewrite ^/minio/ui/(.*) /$1 break;
|
# To support websocket
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header X-NginX-Proxy true;
|
|
||||||
|
|
||||||
# This is necessary to pass the correct IP to be hashed
|
|
||||||
real_ip_header X-Real-IP;
|
|
||||||
|
|
||||||
proxy_connect_timeout 300;
|
|
||||||
|
|
||||||
# To support websockets in MinIO versions released after January 2023
|
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
proxy_set_header Connection "upgrade";
|
proxy_set_header Connection "upgrade";
|
||||||
# Some environments may encounter CORS errors (Kubernetes + Nginx Ingress)
|
|
||||||
# Uncomment the following line to set the Origin request to an empty string
|
|
||||||
# proxy_set_header Origin \'\';
|
|
||||||
chunked_transfer_encoding off;
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
services.nginx.virtualHosts."s3.zoeys.computer" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://localhost${config.services.minio.listenAddress}";
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,11 +40,11 @@ in {
|
||||||
exportGlyphNames = true
|
exportGlyphNames = true
|
||||||
|
|
||||||
[buildPlans.IosevkaCustom.variants]
|
[buildPlans.IosevkaCustom.variants]
|
||||||
inherits = "ss16"
|
inherits = "ss01"
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
noto-fonts
|
noto-fonts
|
||||||
noto-fonts-cjk
|
noto-fonts-cjk-sans
|
||||||
noto-fonts-emoji
|
noto-fonts-emoji
|
||||||
jetbrains-mono
|
jetbrains-mono
|
||||||
(nerdfonts.override {fonts = ["Iosevka" "JetBrainsMono"];})
|
(nerdfonts.override {fonts = ["Iosevka" "JetBrainsMono"];})
|
||||||
|
|
|
||||||
28
packages/sc/default.nix
Normal file
28
packages/sc/default.nix
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
writeShellScriptBin,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
writeShellScriptBin "sc" ''
|
||||||
|
|
||||||
|
# Take a screenshot with grim and slurp
|
||||||
|
${lib.getExe pkgs.grim} -g "$(${lib.getExe pkgs.slurp})" /tmp/screenshot.png
|
||||||
|
|
||||||
|
# Upload the screenshot and store the response
|
||||||
|
response=$(${lib.getExe pkgs.curl} -s \
|
||||||
|
-X POST \
|
||||||
|
-H "Accept: application/json" \
|
||||||
|
-H "Authorization: Bearer Z4MYrYtJUb3Y8VvJynkWAw9eBVU3kvvW9gQ50--hROw" \
|
||||||
|
-F "file=@/tmp/screenshot.png" \
|
||||||
|
https://zoeys.computer/api/images/create)
|
||||||
|
|
||||||
|
# Extract the URL using jq and copy to clipboard
|
||||||
|
echo "$response" | ${lib.getExe pkgs.jq} -r '.url' | ${pkgs.wl-clipboard}/bin/wl-copy
|
||||||
|
|
||||||
|
# Clean up the temporary file
|
||||||
|
rm /tmp/screenshot.png
|
||||||
|
|
||||||
|
# Notify user
|
||||||
|
echo "Screenshot uploaded and URL copied to clipboard!"
|
||||||
|
''
|
||||||
|
|
@ -151,7 +151,7 @@
|
||||||
in
|
in
|
||||||
buildStdenv.mkDerivation rec {
|
buildStdenv.mkDerivation rec {
|
||||||
pname = "zen-browser-unwrapped";
|
pname = "zen-browser-unwrapped";
|
||||||
version = "1.0.1-a.12";
|
version = "1.0.1-a.13";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "zen-browser";
|
owner = "zen-browser";
|
||||||
|
|
@ -159,7 +159,7 @@ in
|
||||||
rev = "${version}";
|
rev = "${version}";
|
||||||
leaveDotGit = true;
|
leaveDotGit = true;
|
||||||
fetchSubmodules = true;
|
fetchSubmodules = true;
|
||||||
hash = "sha256-O5S468G+2fF11mnjR8lMSVBOTRe/X5VxfBLAEVh2mA0=";
|
hash = "sha256-z1YIdulvzkbSa266RZwBbYbeHqY22RvdHAdboR9uqig=";
|
||||||
};
|
};
|
||||||
|
|
||||||
firefoxVersion = (lib.importJSON "${src}/surfer.json").version.version;
|
firefoxVersion = (lib.importJSON "${src}/surfer.json").version.version;
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@
|
||||||
environment.systemPackages = [
|
environment.systemPackages = [
|
||||||
pkgs.BeatSaberModManager
|
pkgs.BeatSaberModManager
|
||||||
pkgs.sbctl
|
pkgs.sbctl
|
||||||
pkgs.custom.vesktop
|
pkgs.vesktop
|
||||||
pkgs.mangohud
|
pkgs.mangohud
|
||||||
pkgs.transmission_4
|
pkgs.transmission_4
|
||||||
inputs.agenix.packages.${system}.agenix
|
inputs.agenix.packages.${system}.agenix
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,8 @@
|
||||||
services.gh.enable = true;
|
services.gh.enable = true;
|
||||||
services.fail2ban.enable = true;
|
services.fail2ban.enable = true;
|
||||||
|
|
||||||
|
ui.fonts.enable = true;
|
||||||
|
|
||||||
age.secrets = {
|
age.secrets = {
|
||||||
zc_key = {
|
zc_key = {
|
||||||
owner = "zoeyscomputer-phx";
|
owner = "zoeyscomputer-phx";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue