• Как улучшить выводимый граф?

    @holllop Автор вопроса
    Максим Припадчев, выражаю огромную благодарность, вы меня привели к ответу. Я принял решение разделить данные на 4 графа. 1. Граф для двойных комбинаций. 2. Граф для тройных комбинаций. 3. Граф для четверных комбинаций. 4. Общий граф(изначальный вариант). Такое решение я принял, чтобы сохранить баланс между полнотой картины и наглядностью. Когда закончу полностью код оставлю его ниже(осталось не много поиграться с получаемой картинкой.)
    Ответ написан
    Комментировать
  • Как автоматическое отправить почты о дни рождения сотрудника на аутлуке всем?

    @holllop
    Да, можно настроить Outlook для отправки автоматических уведомлений о днях рождения сотрудников всему коллективу. Для этого потребуется использовать несколько инструментов, включая Microsoft Power Automate или VBA скрипты в Outlook для автоматизации процесса.
    Ответ написан
    1 комментарий
  • Как определить, загрузился ли скрипт или нет?

    @holllop
    Для того чтобы определить, загружен ли скрипт или находится в процессе загрузки, можно использовать флаги или атрибуты, которые вы могли бы установить в элементе скрипта. В вашем случае, как один из вариантов, можно добавить к элементу скрипта атрибут data-loaded, который будет указывать на его состояние. Для этого вам нужно модифицировать функцию isScript.
    spoiler
    Примерно как-то так, если я правильно понял ход ваших мыслей
    const isScriptLoaded = (url) => {
        const scripts = document.getElementsByTagName('script');
        for(let i = scripts.length; i--;) {
            if(scripts[i].src === url) {
                return scripts[i].getAttribute('data-loaded') === 'true' ? scripts[i] : false;
            }
        }
        return false;
    };
    
    const loadScriptBody = (c) => {
        let url = (c.params) ? arrayToUrlParams(c.url, c.params) : c.url;
        let script = isScriptLoaded(url);
        if(script){
            // Скрипт уже загружен и готов к использованию:
            c.callback();
        } else {
            script = document.createElement('script');
            script.src = url;
            script.setAttribute('data-loaded', 'false');  // Устанавливаем флаг загруженности в 'false'
            script.addEventListener("load", () => {
                script.setAttribute('data-loaded', 'true'); // Меняем флаг на 'true', когда скрипт загрузился
                c.callback();
            }, false);
    
            if(c.attributes && c.attributes.length > 0){
                for(let i = 0; i < c.attributes.length; i++){
                    script.setAttribute(c.attributes[i].name, c.attributes[i].value);
                }
            }
            document.getElementsByTagName('head')[0].appendChild(script);
        }
    };
    Ответ написан
    7 комментариев
  • Хотелось бы узнать мнение болле опытных разработчиков?

    @holllop Автор вопроса
    На данный момент переделал функции
    function createValuesTemplate(length) {
      const numColumns = 9; 
      const placeholders = [];
      let placeholderIndex = 1; 
    
      for (let i = 0; i < length; i++) {
        let rowPlaceholders = [];
        for (let j = 0; j < numColumns; j++) {
          rowPlaceholders.push('$' + placeholderIndex++);
        }
        placeholders.push('(' + rowPlaceholders.join(', ') + ')');
      }
    
      return placeholders.join(', ');
    }
    
    async function accepting_expenses_array(req, res) {
      const expenses_array = req.body;
      const expenses_as_numbers = expenses_array.map(Number);
      console.log("expenses_as_numbers",expenses_as_numbers)
      try {
        // Первое число - id_order. Ищем максимальный id_work
        const results = await pool.query('SELECT id_work FROM "works" WHERE id_order = $1', [expenses_as_numbers[0]]);
        
        const work_id_array = results.rows.map(row => row.id_work);
        const work_id_max = Math.max(...work_id_array);
        console.log("work_id_max",work_id_max)
    
        const expensesWithoutFirst = expenses_as_numbers.slice(1); // Игнорируем первый элемент, id_order
    
        const newExpensesArray = [];
        for (let i = 0; i < expensesWithoutFirst.length; i += 8) {
          // Добавляем work_id_max в начало каждой строки значений
          newExpensesArray.push(work_id_max, ...expensesWithoutFirst.slice(i, i + 8));
        }
        console.log("newExpensesArray",newExpensesArray)
        if (newExpensesArray.length % 9 !== 0) {
          return res.status(400).json({
            success: false,
            error: 'Количество элементов в массиве расходов должно быть кратным числу столбцов таблицы (включая work_id_max).'
          });
        }
        
        // Подготовка SQL запроса на вставку
        const insertQuery = `INSERT INTO "expenses" (
          n_plan, 
          type_work_id, 
          printer_id, 
          material_id,
          format_id, 
          performer_id, 
          n_sheets, 
          n_page, 
          n_ruined
        ) VALUES ${createValuesTemplate(newExpensesArray.length / 9)};;`
    
        console.log("createValuesTemplate(newExpensesArray.length / 9)",createValuesTemplate(newExpensesArray.length / 9))
    
        // Выполняем запрос на вставку с newExpensesArray
        const insertResult = await pool.query(insertQuery, newExpensesArray);
        console.log("insertResult",insertResult);
        // Отправляем успешный ответ
        return res.json({ success: true, message: 'Данные успешно добавлены.' });
      } catch (error) {
        // Логирование ошибки и отправка ошибочного ответа
        console.error('Error during query execution:', error.stack);
        return res.status(500).json({
          success: false,
          error: error.message
        });
      }
    }

    выяснил что пакетная вставка быстрее
    Добил до конца, то что хотел. Работает как задумано
    Ответ написан
    Комментировать
  • Как составить сложный агрегированный запрос?

    @holllop Автор вопроса
    Правильный sql запрос для того чтобы реализовать, то что я хотел выглядит так
    SELECT 
          o.order_id, 
          d.name AS dname, 
          c.customer, 
          o.date, 
          array_agg(
            json_build_object(
              'id_works', w.id_work::text, 
              'name_object', w.name_object, 
              'work_items', subq.work_items
            )
          ) AS works_info
          FROM "order" o
          JOIN works w ON o.order_id = w.id_order
          JOIN departaments d ON o.departament_id = d.departament_id
          JOIN customers c ON o.customer_id = c.customer_id
          LEFT JOIN (
            SELECT
                w.id_work,
                w.name_object,
                json_agg(json_build_object(
                    'n_works', e.n_work::text,
                    'type_works', tw.type_work,
                    'printers', pr.printer,
                    'materials', ma.material,
                    'performers', pe.performer,
                    'formats', f.format,
                    'n_sheets', e.n_sheets::text
                )) AS work_items
            FROM works w
            LEFT JOIN expenses e ON w.id_work = e.n_plan
            LEFT JOIN type_work tw ON e.type_work_id = tw.type_work_id
            LEFT JOIN printer pr ON e.printer_id = pr.printer_id
            LEFT JOIN material ma ON e.material_id = ma.material_id
            LEFT JOIN performers pe ON e.performer_id = pe.performer_id
            LEFT JOIN format f ON e.format_id = f.format_id
            GROUP BY w.id_work, w.name_object
          ) AS subq ON w.id_work = subq.id_work
        GROUP BY o.order_id, d.name, c.customer, o.date
    Ответ написан
    Комментировать
  • Как обработать массив переменной длины?

    @holllop Автор вопроса
    Сначала хочу выразить великую благодарность IvanU7n, он меня подтолкнул к ответу
    function accepting_expenses_array(req, res) {
      const expenses_array = req.body;
      const expenses_as_numbers = expenses_array.map(Number);
      
      // Определяем MAX(id_work) из таблицы "works"
      pool.query('SELECT MAX(id_work) FROM "works"', (error, maxResult) => {
        if (error) {
          throw error;
        }
        const maxIdWork = maxResult.rows[0].max;
    
        // Формируем INSERT-запрос и значения для вставки
        let insertQuery = 'INSERT INTO "expenses" (n_plan, type_work_id, printer_id, material_id, performer_id, format_id, n_sheets, n_page, n_ruined) VALUES ';
        let values = [];
        
        for (let i = 1; i < expenses_as_numbers.length; i += 8) {
          if (i !== 0) {
            insertQuery += ', ';
          }
          insertQuery += `($${1}, $${i + 1}, $${i + 2}, $${i + 3}, $${i + 4}, $${i + 5}, $${i + 6}, $${i + 7}, $${i + 8})`;
          // Формируем значения для вставки
          values.push(maxIdWork, ...expenses_as_numbers.slice(i, i + 8));
        }
        
        console.log(values);
        console.log(insertQuery);
      });
    }

    в консоле получаю
    INSERT INTO "expenses" (n_plan, type_work_id, printer_id, material_id, performer_id, format_id, n_sheets, n_page, n_ruined) VALUES , ($1, $2, $3, $4, $5, $6, $7, $8, $9), ($1, $10, $11, $12, $13, $14, $15, $16, $17), ($1, $18, $19, $20, $21, $22, $23, $24, $25), ($1, $26, $27, $28, $29, $30, $31, $32, $33)

    а это именно, то чего я хотел достичь
    Ответ написан
    Комментировать
  • Не приходит в голову алгоритм лучше. Как сделать лучше?

    @holllop Автор вопроса
    В моём конкретном случае решением будет
    if(clickCount > 1){
                for (let i = 2; i <= clickCount; i++) {
                    elementstypeWorkFirst[i-2].innerHTML = '';
                }
            }
    Ответ написан
    1 комментарий
  • Ошибка при запуске проекта на node js?

    @holllop
    Судя по всему в вашем файле app.js на 23 строке ошибка. Да и предоставьте код того, что вы пытаетесь запустить на Node. А то так сложно сказать что не так.
    Ответ написан
    Комментировать
  • Как обеспечить возможность одновременного вызова эндпойнта, пишущего в БД?

    @holllop
    Попытаюсь ответить как-то комплексно.
    Дедлоки в базе данных могут быть вызваны различными причинами, такими как конфликты параллельных транзакций, блокировки на ресурсы и другие. В вашем случае, если у вас возникают дедлоки при одновременных запросах, использование транзакций может помочь, но вам также необходимо управлять блокировками и избегать конфликтов. То есть воспользоваться блокировкой на уровне строки (Row Locking) и блокировкой на уровне транзакции (Transaction Locking) это всё механизмы Sequelize. Вполне возможно, что даже при использовании этих механизмов могут остаться дедлоки. И в таком случае использование Redis будет необходимо.
    Ответ написан
    2 комментария
  • Как добавить сайт в nginx с помощью node js?

    @holllop
    Я бы рекомендовал сразу на Node.js поставить модуль fs в вашем вопросе не как без него.
    Например
    1. Добавить новые конфигурации сайта в общий файл nginx conf.
    можно примерно таким образом.
    const fs = require('fs');
    const path = require('path');
    
    const nginxConfPath = '/etc/nginx/nginx.conf'; // путь к вашему файлу nginx.conf
    
    // Чтение содержимого nginx.conf
    const nginxConfContent = fs.readFileSync(nginxConfPath, 'utf8');
    
    // Дополнение новыми настройками
    const newConfig = 
        server {
            listen 80;
            server_name example.com;
            location / {
                root /path/to/new/website;
                index index.html;
            }
        }
    ;
    
    const updatedNginxConfContent = nginxConfContent + newConfig;
    
    // Запись измененного содержимого обратно в файл nginx.conf
    fs.writeFileSync(nginxConfPath, updatedNginxConfContent, 'utf8');

    2. Создать папку сайта.

    const newWebsitePath = '/path/to/new/website'; // путь к новой папке сайта
    
    // Создание папки
    fs.mkdirSync(newWebsitePath);

    в остальном не очень уверен по этому наверное лучше не буду писать )
    Ответ написан
    2 комментария
  • Бесконечная загрузка страницы, как исправить?

    @holllop Автор вопроса
    Причина, по которой у меня возникала бесконечная загрузка, заключается в том, что когда я изменял массив orderData внутри цикла for. Это приводит к изменению длины массива, а следовательно, к изменению условия цикла for, которое проверяет i < orderData.length. В результате, цикл может выполняться бесконечное количество раз, вызывая бесконечную загрузку.
    Проблему решил так
    function processing (orderData, workData, workObjectData){
      console.log("доступны и в функции", orderData, workData, workObjectData);
      const updatedOrderData = [];
      for (let i = 0; i < orderData.length; i++) {
        const orderId = orderData[i].order_id;
        const matchingWorkItems = workData.filter(workItem => workItem.id_order === orderId);
        if (matchingWorkItems.length > 0) {
          matchingWorkItems.forEach(workItem => {
            updatedOrderData.push({ ...orderData[i], name_object: workItem.name_object });
          });
        }
        updatedOrderData.push(orderData[i]);
      }
      console.log("updatedOrderData", updatedOrderData);
    }

    так же хочу поблагодарить iljaGolubev за подсказку по оптимизации
    Ответ написан
    1 комментарий
  • Запутался с логикой. Не могу найти решение?

    @holllop Автор вопроса
    в итоге сделал так понимаю что это не лучший вариант, но хоть работает. Буду ещё думать, как оптимизировать весь процесс.
    var orderNumber = document.getElementById('id_order').value;
      var department = document.getElementById('department').value;
      var customer = document.getElementById('customer').value;
      var contractNumber = document.getElementById('id_contract').value;
      var objectName = document.getElementById('name_object').value;
      var orderDate = document.getElementById('date_contract').value;
      var note = document.getElementById('note').value;
    
      // Создаем массив с полученными значениями
      var valuesArray = [orderNumber, department, customer, contractNumber, objectName, orderDate, note];
      
      // Получаем значения из блоков <td>
    var tdElements = document.getElementsByClassName('val');
    var tdValuesArray = [];
    for (var i = 0; i < tdElements.length; i++) {
      var value = tdElements[i].value;
      tdValuesArray.push(value);
    }
    
    var tdInputs = document.getElementsByClassName('number');
    var tdInputArray =[];
    
    for (var i = 0; i < tdInputs.length; i++){
      var value = tdInputs[i].value;
      tdInputArray.push(value);
    }
    
    var printer_line = tdValuesArray.concat(tdInputArray);
    var mergedArray =valuesArray.concat(printer_line);
    
    if (isAddFormatClicked == false && isAddRowClicked == false){
      spetional();
    }
    
    handleAddFormat();
    
    if (isAddRowClicked == true){
      const selectElements1 = document.querySelectorAll('.val1');
      var selectElementsArray1 = [];
      for (var i = 0; i < selectElements1.length; i++) {
        var value = selectElements1[i].value;
        selectElementsArray1.push(value);
      }
    
      var tdInputs1 = document.getElementsByClassName('number1');
      var tdInputArray1 =[];
    
      for (var i = 0; i < tdInputs1.length; i++){
        var value = tdInputs1[i].value;
        tdInputArray1.push(value); 
      }
    
      var printer_line1 =  selectElementsArray1.concat(tdInputArray1);
      console.log("Что в printer_line1", printer_line1);
      console.log("чё тут",isAddFormatClicked1, selectedFormat1)
      main_condition(selectElements1);
      setTimeout(()=>{
        additional_dispatch1();
        console.log("printer_line1 не завимо была ли нажата кнопка", printer_line1)
      },1000);
    }
    
    async function main_condition(selectElements1) {
      console.log("доступ к isAddFormatClicked1, selectedFormat1 в фукции",isAddFormatClicked1, selectedFormat1)
      if (isAddFormatClicked1 == true) {
        if(selectedFormat1 == null){
          console.log("проверка доступен ли массив selectElements1", selectElements1);
          const newSelect = document.createElement('select1');
          const selectedPrinterId = selectElements[1].value;
          console.log("что в newSelect, selectedPrinterId", newSelect, selectedPrinterId);
          setTimeout(async () => {
            const selectedFormat = await fetchDataAndProcess(newSelect, selectedPrinterId);
            console.log("прошёл selectedFormat", selectedFormat);
            printer_line1.splice(5, 1);
            printer_line1.splice(5, 0, selectedFormat.toString());
            additional_dispatch1()
          },2000);
        }else{
          setTimeout(async () => {
            console.log("проверяю что selectedFormat1 точно не null", selectedFormat1);
            printer_line1.splice(5, 1);
            printer_line1.splice(5, 0, selectedFormat1.toString());
            additional_dispatch1()
          },2000);
        }
      }
    }
    
    async function handleAddFormat(){
      console.log("handleAddFormat в нём", isAddFormatClicked, selectedFormat)
      if(isAddFormatClicked == true){
        printer_line.splice(5, 1);
        if(selectedFormat == null){
          const newSelect = document.createElement('select');
          const selectedPrinterId = selectElements[1].value;
          const selectedFormat = await fetchDataAndProcess(newSelect, selectedPrinterId);
          printer_line.splice(5, 0, selectedFormat.toString());
          main_dispatch();
          additional_dispatch();
        } else{
            console.log("я сюда то зашёл или нет")
            printer_line.splice(5, 0, selectedFormat.toString());
            main_dispatch();
            additional_dispatch();
          }
      }else{
        main_dispatch();
      }
    }
    
    async function spetional(){
      if(isAddFormatClicked == true){
        main_dispatch();
        printer_line.splice(5, 1);
        if(selectedFormat == null){
          const newSelect = document.createElement('select');
          console.log("доступ к selectElements", selectElements[1].value);
          const selectedPrinterId = selectElements[1].value;
          const selectedFormat = await fetchDataAndProcess(newSelect, selectedPrinterId);
          printer_line.splice(5, 0, selectedFormat.toString());
          main_dispatch();
          additional_dispatch();
        } else{
            printer_line.splice(5, 0, selectedFormat.toString());
            additional_dispatch();
          }
        }
      }
    
    function main_dispatch(){
      console.log("Отправка  записи valuesArray + printer_line", mergedArray)
      fetch('http://:3000/main_entry', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(mergedArray)
      })
      .then(response => response.json())
      .then(data => console.log(data))
      .catch(error => console.error(error));
    }
    
    function additional_dispatch(){
      console.log("отправка printer_line", printer_line)
      fetch('http://:3000/small_main_entry', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
          body: JSON.stringify(printer_line)
        })
      .then(response => response.json())
      .then(data => console.log(data))
      .catch(error => console.error(error));
    }
    
    function additional_dispatch1(){
      console.log("отправка printer_line1", printer_line1)
      setTimeout(()=>{
        fetch('http://:3000/small_main_entry', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
          body: JSON.stringify(printer_line1)
        })
      .then(response => response.json())
      .then(data => console.log(data))
      .catch(error => console.error(error));
      }, 1000);
    }
    
    async function fetchDataAndProcess(newSelect, selectedPrinterId) {
      try {
        const url = `http://:3000/printer_format?printer_id=${encodeURIComponent(selectedPrinterId)}`;
        const keyVal = 'format_id';
        const keyText = 'format';
    
        const response = await fetch(url);
        const jsonData = await response.json();
        const result = jsonData.map(item => item[keyVal]);
    
        const myVariable = result.map(Number);
        for (const element of myVariable) {
          console.log(typeof element); // number
        }
        const minValue = Math.min(...myVariable);
        return minValue;
      } catch (error) {
        console.error(error);
      }
    Ответ написан
    Комментировать
  • Подключаюсь к сети через Wi-Fi с ноутбука и пишет, что сети без доступа к интернету. Почему?

    @holllop Автор вопроса
    Короче смотрел вчера долго, что не так. Потом я просто сбросил вообще все настройки роутера. Настроил его по новой (как было) и оно заработало ) За помощь благодарю Drno, CityCat4, pindschik. Вы реально помогли
    Ответ написан
    Комментировать
  • Куда развиваться верстальщику?

    @holllop
    Да и в целом от верстки я не получаю супер эмоций, помню когда-то давно создавал телеграм бота, по ощущениям было интересней. Т.е. наверное мне стоит уходить в бэк. Учить там nodejs какой-нибудь. Но какие перспективы? Буду ли я заниматься чем-то сложнее чем во фронте. Или все таки стоит сменить направление?

    сложно сказать стоит вам уходить ли в бэк написание одной программы не делает вас экспертом в этой области. Может вам повезло и вы не схватили все подводные камни, которые могли и вам кажется вау это так классно. (Всегда кажется, что у соседа морковка больше чем у тебя на грядке). Попробуйте написать бота посложнее и/или несколько может это ваше. Если очень кажется что вы хотите бэк, так в чём вопрос возьмите и попробуйте поднимите на какой-то ноде или пхп API( или сразу попробуйте написать базу данных подключить к ноде или пхп и работать с ней).
    Я думаю, что не буду добавлять, что сайты есть разные. И что для вас сложно, а что легко (или интересно/неинтересно) можете знать только вы. И вам довольно правильно отвечали до меня, что есть и социальные сети (которые по сути сайты) и большие компании со сложной структурой и сайтами. Просто по вашему написанному создается впечатление что вы только перекрашивали и передвигали блоки и сложных сайтов вообще не видели.
    Ответ написан
    Комментировать
  • SyntaxError: Unexpected token 'P', "POST-запро"... is not valid JSON, как исправить эту ошибку?

    @holllop Автор вопроса
    у меня ошибка. я не правильно обрабатывал на сервере. Спасибо Михаил Р., он помог обнаружить ошибку.
    Ответ написан
    Комментировать
  • Как получить список файлов, начиная с определенного файла и заканчивая через определенное количество файлов?

    @holllop
    это какое-то задание, а не вопрос.
    но всё же отвечу
    $startFile = 'file3.ex';
    $fileCount = 10;
    
    // Получаем список файлов в папке
    $files = scandir('/путь/к/папке');
    
    // Находим индекс стартового файла
    $startIndex = array_search($startFile, $files);
    
    // Если стартовый файл найден
    if ($startIndex !== false) {
        // Отрезаем часть массива от стартового индекса
        $slicedFiles = array_slice($files, $startIndex, $fileCount);
    
        // Выводим список файлов
        foreach ($slicedFiles as $file) {
            echo $file . PHP_EOL;
        }
    } else {
        echo 'Стартовый файл не найден.';
    }
    Ответ написан
    6 комментариев
  • Для чего нужен nodejs?

    @holllop
    Попробую ответить по порядку.
    Node.js является средой выполнения JavaScript, которая работает за пределами браузера, на сервере. Он позволяет разрабатывать серверный код для веб-страниц и веб-приложений. В контексте веб-сервера, Node.js предоставляет возможность создания и запуска сервера, который будет обрабатывать HTTP-запросы и отвечать на них.
    Всё это слишком абстрактно, сложно материализующее в голове понятия... Скажем, есть к примеру хост-провайдер, предоставляющие место для сайта. Он же использует тот же http запрос для отдачи нам нужных файлов? Или взять к примеру php... Про него не говорят, что с его помощью нужно создать веб-сервер?

    Хост-провайдер или хостинг-провайдер - это компания, которая предоставляет услуги хостинга, т.е. предоставляет место на своих серверах для размещения сайтов. Когда вы загружаете веб-страницы на хостинг-провайдер, он использует веб-серверное ПО (например, Node.js, Apache, Nginx) для обработки входящих запросов от клиентов и отдачи файлов, которые запрошены браузерами пользователей.
    что такое веб сервер?

    веб-сервер (например, на базе Node.js или PHP) - это программное обеспечение, которое обрабатывает HTTP-запросы, предоставляет веб-содержимое и выполняет необходимые операции для функционирования веб-приложений. Node.js предлагает возможности для разработки серверного кода на JavaScript, в то время как PHP является отдельным языком программирования со своими инструментами и функциональностью.
    Ответ написан
    Комментировать
  • Как правильно сделать сложный запрос к БД, через Node.js?

    @holllop Автор вопроса
    Прежде чем ответить, хочу поблагодарить kosuha. Ты мне очень помог реально. Как оказалось мне не нужна сложная структура типа GET запрос зависящий от POST запроса(из-за чего у меня и возникала ошибка
    TypeError: Converting circular structure to JSON
        --> starting at object with constructor 'Socket'
        |     property 'parser' -> object with constructor 'HTTPParser'
        --- property 'socket' closes the circle
    )
    дальше я приведу как я решил свою проблему
    клиент-код
    function loadSelectOptions2(url, selectElement) {
      fetch(url)
        .then(response => response.json())
        .then(data => {
          data.forEach(item => {
            const option = createOption(item.printer_id, item.material);
            selectElement.appendChild(option);
          });
        })
        .catch(error => {
          console.error(error);
          // Обработать ошибку
        });
    }
    selectElement2.addEventListener('change', () => {
        const selectedPrinterId = selectElement2.value;
        console.log('selectedPrinterId:', selectedPrinterId);
        // Очистить select3 перед загрузкой новых опций
        selectElement3.innerHTML = '';
        // Загрузить опции для select3 на основе выбранного значения select2
        if (selectedPrinterId) {
          const url = `http://:3000/printer_material?printer_id=${encodeURIComponent(selectedPrinterId)}`;
          loadSelectOptions2(url, selectElement3);
        }
      });

    код сервера
    const http = require('http');
    const express = require('express');
    const bodyParser = require('body-parser');
    const cors = require('cors');
    const db = require('./pool');
    
    const app = express();
    const port = 3000;
    
    app.use(bodyParser.json());
    app.use(
      bodyParser.urlencoded({
        extended: true,
      })
    );
    app.use(cors());
    app.get('/printer_material', (req, res) => {
      const printer_id = parseInt(req.query.printer_id, 10);
    
      console.log('Received printer_id:', printer_id); // Вывод значения в консоль как число
    
      db.getPrinter_material(printer_id, res);
    });
    http.createServer(app).listen(port, () => {
      console.log(`App running on port ${port}.`);
    });

    //pool.js
    const { response } = require('express');
    
    const Pool = require('pg').Pool;
    const pool = new Pool({
      user: '',
      host: '',
      database: '',
      password: '',
      port: 5432,
    });
    
    const getPrinter_material = (printer_id, response) => {
      console.log('Received printer_id:', printer_id); 
    
      pool.connect((error, client, release) => {
        if (error) {
          throw error;
        }
    
        const query = {
          text: `SELECT pr.printer_id, m.material FROM printer_material pm JOIN printer pr ON pm.printer_id = pr.printer_id JOIN material m ON pm.material_id = m.material_id WHERE pr.printer_id = $1`,
          values: [printer_id],
        };
    
        console.log('Query text:', query.text);
    
        client.query(query, (error, results) => {
          release();
    
          if (error) {
            throw error;
          }
    
          console.log(results.rows);
          response.json(results.rows);
        });
      });
    };
    module.exports = {
      getPrinter_material,
    };

    Я не убирал множественные console.log пока они остались так как я часть за частью проверял работоспособность кода
    Ответ написан
    Комментировать
  • Что почитать про практическое использование на JS?

    @holllop
    Дак это не совсем корректный вопрос.
    Что можно почитать про практическое применение JS, ну например:
    - написать плагин сбора любой информации со страницы;
    - сформировать 5 запросов на сервер, получить ответ, обработать;
    - изменить состояние объекта и прочее.

    А что ты уже знаешь ?
    например если брать
    - написать плагин сбора любой информации со страницы;
    то тут зависит что читать от того какой браузер и какую информацию нужно вытащить. Если брать
    - сформировать 5 запросов на сервер, получить ответ, обработать;
    то тут вообще легко берёшь открываешь браузер пишешь как сделать запросы POST/GET в Node.js/PHP. итд
    Ответ написан
    Комментировать
  • Библиотека спектограмма audio?

    @holllop
    Ну Tone.js например
    Ответ написан
    Комментировать