zet-lib 1.4.10 → 1.4.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/Form.js CHANGED
@@ -579,7 +579,10 @@ Form.field = (obj) => {
579
579
  let bodydropzoneview =
580
580
  countFiles == ""
581
581
  ? ""
582
- : `<div class="card-header">${countFiles} <div class="float-end"><span class="icon-small icons-light" title="Download"><img onclick="location.href= '/zdownloads-dropzone/${obj.routeName}/${obj.key}/${obj.dataId}'" class="icons-bg-black gridview icon-image" src="/assets/icons/download.svg"></span> <span class="icon-small icons-light" title="Compress Images"><img onclick="if(window.confirm('Compress Images ?')) {ajaxPost('/zcompress-dropzone',{table:'${obj.routeName}',field:'${obj.key}',id:${obj.dataId}},(data) => toastrForm(data))}" class="icons-bg-black gridextract icon-image" src="/assets/icons/file-zip.svg"></span></div></div>`;
582
+ : `<div class="card-header">${countFiles} <div class="float-end">
583
+ <span class="icon-small icons-light" title="Download"><img onclick="location.href= '/zdownloads-dropzone/${obj.routeName}/${obj.key}/${obj.dataId}'" class="icons-bg-black gridview icon-image" src="/assets/icons/download.svg"></span>
584
+ <span class="icon-small icons-light" title="Compress Images"><img onclick="if(window.confirm('Compress Images ?')) {ajaxPost('/zcompress-dropzone',{table:'${obj.routeName}',field:'${obj.key}',id:${obj.dataId}},(data) => toastrForm(data))}" class="icons-bg-black gridextract icon-image" src="/assets/icons/file-zip.svg"></span>
585
+ </div></div>`;
583
586
  displayForm = `<div id="div-progress"></div><div class="card">
584
587
  ${bodydropzoneview}
585
588
  <div class="card-body">`;
@@ -601,8 +604,17 @@ Form.field = (obj) => {
601
604
  }
602
605
  displayForm += `</div></div>`;
603
606
  break;
607
+
608
+ case "dropbox":
609
+ displayForm = `${prepend}<div ${tabindex} ${style} type="text" ${classview} ${id} ${htmlOptions}><label for="files" class="dropzone-container">
610
+ <div class="dz-message" data-dz-message><div class="file-icon"><span class="icon-small icons-primary"><img class="icons-bg-white icon-image-large" src="/assets/icons/file-plus.svg"></span></div>
611
+ <div class="text-center pt-3 px-5">
612
+ <p class="w-80 h5 text-dark fw-bold">Drag your documents, photos or videos here to start uploading.</p>
613
+ </div></div>
614
+ </label></div>${information}${append}`;
615
+ break;
604
616
  default:
605
- value = value ? value.replaceAll('"', "&quot;") : obj.value;
617
+ value = value ? value.replace(/"/g, "&quot;") : obj.value;
606
618
  displayForm = `${prepend}${inputGroupLeft}<input ${disabled} autocomplete="nope" autofocus="" ${readonly} ${tabindex} type="${type}" class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" data-t="${value}" ${htmlOptions}>${inputGroupRight}${information}${append}`;
607
619
  break;
608
620
  }
package/lib/zAppRouter.js CHANGED
@@ -1,3 +1,4 @@
1
+ require("dotenv").config();
1
2
  const express = require("express");
2
3
  const router = express.Router();
3
4
  const csrf = require("csurf");
@@ -23,7 +24,8 @@ const qs = require("qs");
23
24
  const zip = require("express-zip");
24
25
  const sharp = require("sharp");
25
26
  const path = require("path");
26
-
27
+ const { Dropbox } = require("dropbox");
28
+ const fetch = require("isomorphic-fetch");
27
29
  /*
28
30
  ajax Post
29
31
  */
@@ -403,8 +405,8 @@ router.post("/signup-custom", async (req, res) => {
403
405
  },
404
406
  });
405
407
  /* await zRoute.loginAjax(dataUser.username, body.password, req, res);
406
- //refresh cache
407
- await zCache.renew();*/
408
+ //refresh cache
409
+ await zCache.renew();*/
408
410
 
409
411
  res.json(Util.jsonSuccess("Successfuly"));
410
412
  } catch (e) {
@@ -708,15 +710,15 @@ router.post("/zzapproval", async (req, res) => {
708
710
  if (data.status == 2) {
709
711
  //send activity
710
712
  /* await zRoute.insertSQL(req, res, "zactivity", {
711
- user_id: res.locals.userId,
712
- table: MYMODEL.table,
713
- id_data: data.id,
714
- status: data.status,
715
- status_label: MYMODEL.widgets.status.fields[data.status],
716
- title: MYMODEL.widgets.status.fields[data.status],
717
- description: users[res.locals.userId].fname + " " +users[res.locals.userId].lname ,
718
- data: JSON.stringify(data)
719
- });*/
713
+ user_id: res.locals.userId,
714
+ table: MYMODEL.table,
715
+ id_data: data.id,
716
+ status: data.status,
717
+ status_label: MYMODEL.widgets.status.fields[data.status],
718
+ title: MYMODEL.widgets.status.fields[data.status],
719
+ description: users[res.locals.userId].fname + " " +users[res.locals.userId].lname ,
720
+ data: JSON.stringify(data)
721
+ });*/
720
722
  //if serial
721
723
  if (data.type == 2) {
722
724
  approvers = [approvers[0]];
@@ -786,38 +788,38 @@ router.post("/zzapproval", async (req, res) => {
786
788
  textWa += `Please click the link above to view the document.\r\n${link}`;
787
789
 
788
790
  /* await whatsapp({
789
- to: phone,
790
- text: textWa,
791
- sections: JSON.stringify(sections),
792
- buttonText: "Click me for details"
793
- });*/
791
+ to: phone,
792
+ text: textWa,
793
+ sections: JSON.stringify(sections),
794
+ buttonText: "Click me for details"
795
+ });*/
794
796
  }
795
797
 
796
798
  //send notification
797
799
  /* await zRoute.insertSQL(req, res, "znotification", {
798
- user_id: item,
799
- table: MYMODEL.table,
800
- id_data: data.id,
801
- status: 1,
802
- link: "/za/" + post.token,
803
- status_label: MYMODEL.widgets.status.fields[1],
804
- title: `Need Approve`,
805
- description: data.title,
806
- token: post.token
807
- });*/
800
+ user_id: item,
801
+ table: MYMODEL.table,
802
+ id_data: data.id,
803
+ status: 1,
804
+ link: "/za/" + post.token,
805
+ status_label: MYMODEL.widgets.status.fields[1],
806
+ title: `Need Approve`,
807
+ description: data.title,
808
+ token: post.token
809
+ });*/
808
810
 
809
811
  //send todolist
810
812
  /* await zRoute.insertSQL(req, res, "ztodolist", {
811
- user_id: item,
812
- table: MYMODEL.table,
813
- id_data: data.id,
814
- status: 1,
815
- link: "/za/" + post.token,
816
- status_label: MYMODEL.widgets.status.fields[1],
817
- title: `Need Approve`,
818
- description: data.title,
819
- users: JSON.stringify(allUsers)
820
- });*/
813
+ user_id: item,
814
+ table: MYMODEL.table,
815
+ id_data: data.id,
816
+ status: 1,
817
+ link: "/za/" + post.token,
818
+ status_label: MYMODEL.widgets.status.fields[1],
819
+ title: `Need Approve`,
820
+ description: data.title,
821
+ users: JSON.stringify(allUsers)
822
+ });*/
821
823
 
822
824
  //send toastr using socket.io
823
825
  io.to(users[item].token).emit("message", "Need Approve " + data.title);
@@ -863,50 +865,50 @@ router.post("/zzapproval", async (req, res) => {
863
865
  textWa += "We have some document for you.\r\n";
864
866
  textWa += `Please click the link above to view the document.\r\n${link}`;
865
867
  /* await whatsapp({
866
- to: phone,
867
- text: textWa,
868
- sections: JSON.stringify(sections),
869
- buttonText: "Click me for details"
870
- });*/
868
+ to: phone,
869
+ text: textWa,
870
+ sections: JSON.stringify(sections),
871
+ buttonText: "Click me for details"
872
+ });*/
871
873
  }
872
874
 
873
875
  //send activity
874
876
  /* await cRoute.insertSQL(req, res, "zactivity",{
875
- user_id:item,
876
- table:MYMODEL.table,
877
- id_data:data.id,
878
- status:7,
879
- status_label: MYMODEL.widgets.status.fields[7],
880
- title : MYMODEL.widgets.status.fields[7],
881
- description: data.title,
882
- data:JSON.stringify(data)
883
- });*/
877
+ user_id:item,
878
+ table:MYMODEL.table,
879
+ id_data:data.id,
880
+ status:7,
881
+ status_label: MYMODEL.widgets.status.fields[7],
882
+ title : MYMODEL.widgets.status.fields[7],
883
+ description: data.title,
884
+ data:JSON.stringify(data)
885
+ });*/
884
886
 
885
887
  //send notification
886
888
  /* await zRoute.insertSQL(req, res, "znotification", {
887
- user_id: item,
888
- table: MYMODEL.table,
889
- id_data: data.id,
890
- status: 1,
891
- link: "/za/" + post.token,
892
- status_label: MYMODEL.widgets.status.fields[1],
893
- title: `Need Acknowledge`,
894
- description: data.title,
895
- token: post.token
896
- });
897
-
898
- //send todolist
899
- await zRoute.insertSQL(req, res, "ztodolist", {
900
- user_id: item,
901
- table: MYMODEL.table,
902
- id_data: data.id,
903
- status: 1,
904
- link: "/za/" + post.token,
905
- status_label: MYMODEL.widgets.status.fields[1],
906
- title: `Need Acknowledge`,
907
- description: data.title,
908
- users: JSON.stringify(allUsers)
909
- });*/
889
+ user_id: item,
890
+ table: MYMODEL.table,
891
+ id_data: data.id,
892
+ status: 1,
893
+ link: "/za/" + post.token,
894
+ status_label: MYMODEL.widgets.status.fields[1],
895
+ title: `Need Acknowledge`,
896
+ description: data.title,
897
+ token: post.token
898
+ });
899
+
900
+ //send todolist
901
+ await zRoute.insertSQL(req, res, "ztodolist", {
902
+ user_id: item,
903
+ table: MYMODEL.table,
904
+ id_data: data.id,
905
+ status: 1,
906
+ link: "/za/" + post.token,
907
+ status_label: MYMODEL.widgets.status.fields[1],
908
+ title: `Need Acknowledge`,
909
+ description: data.title,
910
+ users: JSON.stringify(allUsers)
911
+ });*/
910
912
  io.to(users[item].token).emit(
911
913
  "message",
912
914
  "Need Acknowledge " + data.title
@@ -1042,23 +1044,23 @@ router.get("/za/:token", csrfProtection, async (req, res) => {
1042
1044
  if (result.mystatus == 7) {
1043
1045
  MYMODEL = MYMODELS["zapprovals"];
1044
1046
  /* await connection.insert({
1045
- table: "zactivity",
1046
- data: {
1047
- company_id: result.company_id,
1048
- created_at: Util.now(),
1049
- created_by: result.user_id,
1050
- updated_by: result.user_id,
1051
- user_id: result.user_id,
1052
- table: MYMODEL.table,
1053
- id_data: result.ide,
1054
- status: 6,
1055
- status_label: MYMODEL.widgets.status.fields[6],
1056
- title: `${MYMODEL.widgets.status.fields[6]}`,
1057
- description: `Ok `,
1058
- data: JSON.stringify(data)
1059
- }
1060
- });
1061
- */
1047
+ table: "zactivity",
1048
+ data: {
1049
+ company_id: result.company_id,
1050
+ created_at: Util.now(),
1051
+ created_by: result.user_id,
1052
+ updated_by: result.user_id,
1053
+ user_id: result.user_id,
1054
+ table: MYMODEL.table,
1055
+ id_data: result.ide,
1056
+ status: 6,
1057
+ status_label: MYMODEL.widgets.status.fields[6],
1058
+ title: `${MYMODEL.widgets.status.fields[6]}`,
1059
+ description: `Ok `,
1060
+ data: JSON.stringify(data)
1061
+ }
1062
+ });
1063
+ */
1062
1064
 
1063
1065
  await connection.update({
1064
1066
  table: "zapprovals_details",
@@ -1636,6 +1638,7 @@ router.post("/zdropzone-remove", async (req, res) => {
1636
1638
  res.status(500).send(e + "");
1637
1639
  }
1638
1640
  });
1641
+
1639
1642
  router.post("/zdropzone-attributes", async (req, res) => {
1640
1643
  try {
1641
1644
  let userId = res.locals.userId;
@@ -1859,4 +1862,288 @@ router.post("/zcompress-dropzone", async (req, res) => {
1859
1862
  }
1860
1863
  });
1861
1864
 
1865
+ //for dropbox
1866
+ // Initialize Dropbox client
1867
+ let dbx = new Dropbox({
1868
+ accessToken: process.env.DROPBOX_ACCESS_TOKEN,
1869
+ refreshToken: process.env.DROPBOX_REFRESH_TOKEN,
1870
+ clientId: process.env.DROPBOX_CLIENT_ID,
1871
+ clientSecret: process.env.DROPBOX_CLIENT_SECRET,
1872
+ fetch: fetch,
1873
+ });
1874
+
1875
+ // Function to refresh access token
1876
+ async function refreshAccessToken() {
1877
+ try {
1878
+ const response = await fetch("https://api.dropbox.com/oauth2/token", {
1879
+ method: "POST",
1880
+ headers: {
1881
+ "Content-Type": "application/x-www-form-urlencoded",
1882
+ },
1883
+ body: new URLSearchParams({
1884
+ grant_type: "refresh_token",
1885
+ refresh_token: process.env.DROPBOX_REFRESH_TOKEN,
1886
+ client_id: process.env.DROPBOX_CLIENT_ID,
1887
+ client_secret: process.env.DROPBOX_CLIENT_SECRET,
1888
+ }),
1889
+ });
1890
+
1891
+ const data = await response.json();
1892
+
1893
+ if (data.access_token) {
1894
+ // Update the access token in the Dropbox client
1895
+ dbx = new Dropbox({
1896
+ accessToken: data.access_token,
1897
+ refreshToken: process.env.DROPBOX_REFRESH_TOKEN,
1898
+ clientId: process.env.DROPBOX_CLIENT_ID,
1899
+ clientSecret: process.env.DROPBOX_CLIENT_SECRET,
1900
+ fetch: fetch,
1901
+ });
1902
+
1903
+ // Update the .env file with the new access token
1904
+ const envContent = fs.readFileSync(`${dirRoot}/.env`, "utf8");
1905
+ const updatedEnv = envContent.replace(
1906
+ /DROPBOX_ACCESS_TOKEN=.*/,
1907
+ `DROPBOX_ACCESS_TOKEN=${data.access_token}`
1908
+ );
1909
+ fs.writeFileSync(`${dirRoot}/.env`, updatedEnv);
1910
+
1911
+ return data.access_token;
1912
+ } else {
1913
+ throw new Error("Failed to refresh access token");
1914
+ }
1915
+ } catch (error) {
1916
+ console.error("Error refreshing access token:", error);
1917
+ throw error;
1918
+ }
1919
+ }
1920
+
1921
+ // Middleware to handle token refresh
1922
+ async function handleTokenRefresh(req, res, next) {
1923
+ try {
1924
+ // Try to make a test API call
1925
+ await dbx.usersGetCurrentAccount();
1926
+ next();
1927
+ } catch (error) {
1928
+ if (error.status === 401) {
1929
+ try {
1930
+ // Token expired, try to refresh it
1931
+ await refreshAccessToken();
1932
+ next();
1933
+ } catch (refreshError) {
1934
+ res
1935
+ .status(401)
1936
+ .json({ error: "Authentication failed. Please re-authenticate." });
1937
+ }
1938
+ } else {
1939
+ next(error);
1940
+ }
1941
+ }
1942
+ }
1943
+
1944
+ // Serve static files
1945
+ //app.use(express.static('public'));
1946
+ // Create test folder if it doesn't exist
1947
+ //dir = '/test'
1948
+ async function ensureFolder(dir) {
1949
+ try {
1950
+ await dbx.filesCreateFolderV2({
1951
+ path: dir,
1952
+ autorename: false,
1953
+ });
1954
+ } catch (error) {
1955
+ if (error.status !== 409) {
1956
+ // 409 means folder already exists
1957
+ throw error;
1958
+ }
1959
+ }
1960
+ }
1961
+
1962
+ // Function to delay execution
1963
+ const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
1964
+
1965
+ // Upload endpoint
1966
+ router.post("/zdropbox/:table/:field", handleTokenRefresh, async (req, res) => {
1967
+ try {
1968
+ if (!req.files || !req.files.file) {
1969
+ return res.status(400).json({ error: "No file uploaded" });
1970
+ }
1971
+
1972
+ const userId = res.locals.userId;
1973
+ const table = req.params.table;
1974
+ const field = req.params.field;
1975
+ const file = req.files.file;
1976
+ const fileName = file.name;
1977
+ //ensure folder
1978
+ const dir = `/temps/${table}/${field}/${userId}`;
1979
+ await ensureFolder(dir);
1980
+ const filePath = `${dir}/${fileName}`;
1981
+
1982
+ console.log("Uploading file to path:", filePath);
1983
+ console.log("File size:", file.size);
1984
+ console.log("File name:", fileName);
1985
+
1986
+ const response = await dbx.filesUpload({
1987
+ path: filePath,
1988
+ contents: file.data,
1989
+ mode: { ".tag": "add" },
1990
+ autorename: true,
1991
+ });
1992
+ res.json("ok");
1993
+ } catch (error) {
1994
+ console.error("Upload error:", error);
1995
+ console.error("Error details:", {
1996
+ message: error.message,
1997
+ stack: error.stack,
1998
+ response: error.response,
1999
+ });
2000
+ res.status(500).json({
2001
+ error: "Failed to upload file",
2002
+ details: error.message,
2003
+ });
2004
+ }
2005
+ });
2006
+
2007
+ router.post("/zdropbox-attributes", handleTokenRefresh, async (req, res) => {
2008
+ try {
2009
+ let userId = res.locals.userId;
2010
+ let dir = `${dirRoot}/public/zdropzone/${userId}`;
2011
+ if (!fs.existsSync(dir)) {
2012
+ fs.mkdirSync(dir, { recursive: true });
2013
+ }
2014
+ let body = req.body;
2015
+ let category = body.category;
2016
+ let name = `dropbox__${userId}__${body.table}__${body.field}__${body.type}`;
2017
+ //dropzone__${res.locals.userId}__${table}__${key}__create
2018
+ let arr = myCache.has(name) ? myCache.get(name) : [];
2019
+ if (category === "add") {
2020
+ arr.push(body.file);
2021
+ } else {
2022
+ name = `dropzone__${userId}__${body.table}__${body.field}__${body.type}`;
2023
+ if (myCache.has(name)) {
2024
+ arr = myCache.get(name);
2025
+ }
2026
+ arr = Util.arrayDelete(arr, body.file);
2027
+ }
2028
+ myCache.set(name, arr);
2029
+ res.json("ok");
2030
+ } catch (e) {
2031
+ console.log(e);
2032
+ res.status(500).send(e + "");
2033
+ }
2034
+ });
2035
+
2036
+ //get all files and meta in dropbox
2037
+ router.post("/zdropbox-files", handleTokenRefresh, async (req, res) => {
2038
+ let datas = [];
2039
+ const room = res.locals.token;
2040
+ try {
2041
+ const { files, table, field } = req.body;
2042
+ let dir = `/${table}/${field}`;
2043
+ for (file of files) {
2044
+ let pathFile = `${dir}/${file.fileName}`;
2045
+ //console.log(pathFile)
2046
+ try {
2047
+ const metadata = await dbx.filesGetMetadata({
2048
+ path: pathFile,
2049
+ });
2050
+ let link = ``;
2051
+ try {
2052
+ const response = await dbx.filesGetTemporaryLink({
2053
+ path: pathFile,
2054
+ });
2055
+ link = response.result.link;
2056
+ } catch (error) {
2057
+ console.error("Error getting temporary link:", error);
2058
+ io.to(room).emit(
2059
+ "errormessage",
2060
+ `Error getting temporary link: ${error.message}`
2061
+ );
2062
+ }
2063
+
2064
+ const mockFile = {
2065
+ name: metadata.result.name,
2066
+ id: metadata.result,
2067
+ path: metadata.result.path_display,
2068
+ link: link,
2069
+ isImage: metadata.result.name.match(/\.(jpg|jpeg|png|gif)$/i),
2070
+ size: metadata.result.size,
2071
+ modified: metadata.result.server_modified,
2072
+ accepted: true,
2073
+ };
2074
+ //console.log(mockFile)
2075
+ datas.push(mockFile);
2076
+ } catch (e) {
2077
+ console.log(e);
2078
+ io.to(room).emit(
2079
+ "errormessage",
2080
+ `${e.message} Error ${pathFile} not exist in dropbox`
2081
+ );
2082
+ }
2083
+ }
2084
+ } catch (e) {
2085
+ console.log(e);
2086
+ res.status(500).send(e + "");
2087
+ }
2088
+ res.json(datas);
2089
+ });
2090
+
2091
+ // Delete file
2092
+ router.post("/zdropbox-delete/", handleTokenRefresh, async (req, res) => {
2093
+ try {
2094
+ let body = req.body;
2095
+ let path = body.path;
2096
+ const filePath = decodeURIComponent(req.params.path);
2097
+ await dbx.filesDeleteV2({
2098
+ path: filePath,
2099
+ });
2100
+ res.json({ success: true });
2101
+ } catch (error) {
2102
+ console.error("Error deleting file:", error);
2103
+ res.status(500).json({ error: "Error deleting file" });
2104
+ }
2105
+ });
2106
+
2107
+ // Endpoint to check token status
2108
+ router.get("/zdropbox-check-token", handleTokenRefresh, async (req, res) => {
2109
+ try {
2110
+ await dbx.usersGetCurrentAccount();
2111
+ res.json({ status: "valid" });
2112
+ } catch (error) {
2113
+ res.status(401).json({ status: "invalid" });
2114
+ }
2115
+ });
2116
+
2117
+ // Get temporary link for a file
2118
+ router.post("/zdropbox-get-temp-link", handleTokenRefresh, async (req, res) => {
2119
+ try {
2120
+ const response = await dbx.filesGetTemporaryLink({
2121
+ path: req.body.path,
2122
+ });
2123
+ res.json({ link: response.result.link });
2124
+ } catch (error) {
2125
+ console.error("Error getting temporary link:", error);
2126
+ res.status(500).json({ error: "Error getting temporary link" });
2127
+ }
2128
+ });
2129
+
2130
+ router.get(
2131
+ "/zdropbox-view/:table/:field/:item",
2132
+ handleTokenRefresh,
2133
+ async (req, res) => {
2134
+ try {
2135
+ let item = req.params.item;
2136
+ item = item.substring(13);
2137
+ let filePath = `/${req.params.table}/${req.params.field}/${req.params.item}`;
2138
+ const response = await dbx.filesGetTemporaryLink({
2139
+ path: filePath,
2140
+ });
2141
+ res.send(`<img src="${response.result.link}">`);
2142
+ } catch (e) {
2143
+ console.log(e);
2144
+ res.send(e);
2145
+ }
2146
+ }
2147
+ );
2148
+
1862
2149
  module.exports = router;
package/lib/zRoute.js CHANGED
@@ -2,6 +2,7 @@
2
2
  * For default route controller
3
3
  * service for routes
4
4
  */
5
+ require("dotenv").config();
5
6
  const excelToJson = require("convert-excel-to-json");
6
7
  const qs = require("qs");
7
8
  //for generate PDF
@@ -20,6 +21,7 @@ const debug = require("./debug");
20
21
  const moduleLib = require("./moduleLib");
21
22
  const cForm = require("./Form");
22
23
  const readXlsxFile = require("read-excel-file/node");
24
+ const { Dropbox } = require("dropbox");
23
25
 
24
26
  const zRoute = {};
25
27
 
@@ -1265,6 +1267,20 @@ zRoute.dataTableData = (
1265
1267
  }
1266
1268
  break;
1267
1269
 
1270
+ case "dropbox":
1271
+ if (myvalue && myvalue.length > 0) {
1272
+ if (typeof myvalue === "string") {
1273
+ value = [myvalue];
1274
+ }
1275
+ myvalue = value.map(
1276
+ (item) =>
1277
+ `<a class="text-success" target="_blank" href="/zdropbox-view/${
1278
+ MYMODEL.routeName
1279
+ }/${key}/${item}"> ${item.substring(13)}</a> `
1280
+ );
1281
+ }
1282
+ break;
1283
+
1268
1284
  case "password":
1269
1285
  myvalue = "xxxxxx";
1270
1286
  break;
@@ -3031,7 +3047,7 @@ zRoute.forms = (
3031
3047
  if (widgets[key].hidden) {
3032
3048
  obj.type = "hidden";
3033
3049
  } else {
3034
- obj.value = obj.value.replaceAll('"', "&quot;") || "";
3050
+ obj.value = obj.value ? obj.value.replace(/"/g, "&quot;") : "";
3035
3051
  obj.type = "input";
3036
3052
  }
3037
3053
  break;
@@ -3090,6 +3106,33 @@ zRoute.forms = (
3090
3106
  obj.type = "dropzone";
3091
3107
  obj.class = "dropzone boxy-tiny d-block";
3092
3108
  break;
3109
+ case "dropbox":
3110
+ let dropbox_data_arr = [];
3111
+ if (obj.value.length > 0) {
3112
+ let dropfiles = obj.value || [];
3113
+ if (typeof obj.value == "string") {
3114
+ dropfiles = [obj.value];
3115
+ }
3116
+ dropfiles.map((item) => {
3117
+ let filename = item; //`${dirRoot}/public/uploads/${MYMODEL.table}/${key}/${item}`;
3118
+ var fileSizeInBytes = 12345;
3119
+ if (Util.fileExist(filename)) {
3120
+ var stats = fs.statSync(filename);
3121
+ fileSizeInBytes = stats.size;
3122
+ }
3123
+ dropbox_data_arr.push({ fileName: item, size: fileSizeInBytes });
3124
+ });
3125
+ myCache.set(
3126
+ `dropbox_${res.locals.userId}__${MYMODEL.table}__${key}__${data.id}`,
3127
+ obj.value
3128
+ );
3129
+ }
3130
+ let dropboxValue =
3131
+ obj.value.length > 0 ? JSON.stringify(dropbox_data_arr) : "[]";
3132
+ script += `let dropbox_${key}_data = ${dropboxValue};`;
3133
+ obj.type = "dropbox";
3134
+ obj.class = "dropzone boxy-tiny d-block";
3135
+ break;
3093
3136
  case "lexical":
3094
3137
  obj.type = "lexical";
3095
3138
  if (obj.value) {
@@ -3953,6 +3996,7 @@ zRoute.generateJS = (req, res, MYMODEL, relations, zForms = "", data = {}) => {
3953
3996
  let hasDateTimePicker = false;
3954
3997
  let hasDropzone = false;
3955
3998
  let dropzones = [];
3999
+ let dropboxes = [];
3956
4000
  let hasTable = false;
3957
4001
  let chainsObj = {};
3958
4002
  let chainsArr = [];
@@ -3964,6 +4008,7 @@ zRoute.generateJS = (req, res, MYMODEL, relations, zForms = "", data = {}) => {
3964
4008
  let hasLexical = false;
3965
4009
  let hasLocation = false;
3966
4010
  let hasDragdrop = false;
4011
+ let hasDropbox = false;
3967
4012
  let lexicals = [];
3968
4013
  let mapKey = "";
3969
4014
  let hasAttributes = [];
@@ -4035,6 +4080,9 @@ zRoute.generateJS = (req, res, MYMODEL, relations, zForms = "", data = {}) => {
4035
4080
  } else if (widgets[key].name == "dropzone") {
4036
4081
  hasDropzone = true;
4037
4082
  dropzones.push(key);
4083
+ } else if (widgets[key].name == "dropbox") {
4084
+ hasDropbox = true;
4085
+ dropboxes.push(key);
4038
4086
  }
4039
4087
  // has chains
4040
4088
  if (widgets[key].name == "relation") {
@@ -4073,7 +4121,7 @@ zRoute.generateJS = (req, res, MYMODEL, relations, zForms = "", data = {}) => {
4073
4121
  headObj.clockpicker = clockpickerObj.head;
4074
4122
  endObj.clockpicker = clockpickerObj.end;
4075
4123
  }
4076
- if (hasDropzone) {
4124
+ if (hasDropzone || hasDropbox) {
4077
4125
  let dropzoneObj = moduleLib.dropzone(req, res);
4078
4126
  headObj.dropzone = dropzoneObj.head;
4079
4127
  endObj.dropzone = dropzoneObj.end;
@@ -4238,7 +4286,6 @@ zRoute.generateJS = (req, res, MYMODEL, relations, zForms = "", data = {}) => {
4238
4286
  window.open(src, '_blank');
4239
4287
  })
4240
4288
  }
4241
-
4242
4289
  })
4243
4290
  },1000)
4244
4291
  };
@@ -4247,6 +4294,69 @@ zRoute.generateJS = (req, res, MYMODEL, relations, zForms = "", data = {}) => {
4247
4294
  });
4248
4295
  }
4249
4296
 
4297
+ if (hasDropbox) {
4298
+ dropboxes.map((item) => {
4299
+ scriptForm += `$("div#${item}").dropzone({
4300
+ url: "/zdropbox/${MYMODEL.table}/${item}",
4301
+ paramName: "file",
4302
+ addRemoveLinks: !0,
4303
+ maxFilesize: 30,
4304
+ headers: {"X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content")},
4305
+ removedfile: function(file) {
4306
+ const type = window.location.href.split("/").pop();
4307
+ ajaxPost("/zdropbox-remove",{file:file.name, cname:"dropbox__ZUSER___ID__${MYMODEL.table}__${item}__"+type},(data) => {
4308
+ file.previewElement.remove();
4309
+ })
4310
+ },
4311
+ init: function() {
4312
+ let dz = this;
4313
+ const type = window.location.href.split("/").pop();
4314
+ dz.on("addedfile", function(file) {
4315
+ ajaxPost("/zdropbox-attributes",{file:file.name,'category':'add',field:"${item}",table:"${MYMODEL.table}", type:type},() => {})
4316
+ });
4317
+ dz.on("removedfile", function(file) {
4318
+ ajaxPost("/zdropbox-attributes",{file:file.name,'category':'remove',field:"${item}",table:"${MYMODEL.table}", type:type},() => {});
4319
+ $("div#${item}").find(".dz-message").remove();
4320
+ });
4321
+ if(dropbox_${item}_data.length > 0) {
4322
+ ajaxPost('/zdropbox-files',{files:dropbox_${item}_data,table:"${MYMODEL.table}",field:"${item}"}, function(datas) {
4323
+ datas.map((mockFile) => {
4324
+ dz.options.addedfile.call(dz, mockFile);
4325
+ dz.options.thumbnail.call(dz, mockFile, mockFile.link);
4326
+ const imageElement = mockFile.previewElement.querySelector('.dz-image');
4327
+ $(imageElement).addClass("divzdropbox")
4328
+ let ext = mockFile.name.toLowerCase().split(".").pop();
4329
+ imageElement.setAttribute('data-ext', ext);
4330
+ imageElement.setAttribute('data-name', mockFile.name);
4331
+ imageElement.setAttribute('data-link', mockFile.link);
4332
+ $(imageElement).attr('id', mockFile.id.content_hash);
4333
+ $(imageElement).css('z-index',9999)
4334
+ })
4335
+ let time = datas.length <10 ? 2000 : 4000;
4336
+ setTimeout(function(){
4337
+ $(".divzdropbox").each(function () {
4338
+ let ext = $(this).attr('data-ext');
4339
+ if (ext == "gif" || ext == "png" || ext == "jpeg" || ext == "jpg" || ext == "bmp" || ext == "webp" || ext == "jiff" || ext == "svg" || ext == "avif") {
4340
+ $(this).on("click", function () {
4341
+ $(".zimage-modal").attr('src', $(this).attr('data-link')).attr('data-name', $(this).attr('data-name'));
4342
+ $("#zmodal-image").modal("show");
4343
+ })
4344
+ } else {
4345
+ let file = nonImagesTypeObject[ext] || 'file.png';
4346
+ $(this).find("img").attr("src", "/img/" + file);
4347
+ $(this).on("click", function () {
4348
+ window.open($(this).attr('data-link'), '_blank');
4349
+ })
4350
+ }
4351
+ })
4352
+ },time);
4353
+ })
4354
+ }
4355
+ }
4356
+ }); `;
4357
+ });
4358
+ }
4359
+
4250
4360
  defaultScript = `${Util.newLine} $(function () {
4251
4361
  $(".isfile").each(function (index, value) {
4252
4362
  let filename = $(this).attr("data-filename") || "";
@@ -4261,24 +4371,7 @@ zRoute.generateJS = (req, res, MYMODEL, relations, zForms = "", data = {}) => {
4261
4371
  if (ext == "gif" || ext == "png" || ext == "jpeg" || ext == "jpg" || ext == "bmp" || ext == "webp" || ext == "jiff" || ext == "svg" || ext == "avif") {
4262
4372
  $("#file"+id).attr("src","/uploads/"+table+"/"+filename).attr("width",width+"px");
4263
4373
  } else {
4264
- let file = 'file.png';
4265
- if(ext == "docx" || ext == "doc") {
4266
- file = 'word.png'
4267
- } else if(ext == 'xls' || ext == 'xlsx') {
4268
- file = 'excel.png'
4269
- } else if(ext == 'pdf') {
4270
- file = 'pdf.png'
4271
- } else if(ext == 'ppt' || ext == 'pptx'){
4272
- file = 'ppt.png';
4273
- } else if(ext == 'txt') {
4274
- file = 'txt.png';
4275
- } else if(ext == 'zip') {
4276
- file = 'zip.jpg';
4277
- } else if(ext == 'rar') {
4278
- file = 'rar.jpg';
4279
- } else if(ext == 'rar') {
4280
- file = 'file.png';
4281
- }
4374
+ let file = nonImagesTypeObject[ext] || 'file.png';
4282
4375
  $("#file"+id).attr("src","/img/"+file).attr("height","45px").attr("width","45px").addClass("boxy-small");
4283
4376
  }
4284
4377
  $("#file"+id).on("click", function () {
@@ -4482,7 +4575,7 @@ $("#body-${keys}>tr").each(function (index, tr) {
4482
4575
  var ${keys} = $("#body-${keys}").data("value") ? $("#body-${keys}").data("value") : [];
4483
4576
  ${keys}.forEach(function (myobj, index) {
4484
4577
  build${keys}form(index, myobj);
4485
- });
4578
+ });
4486
4579
  });${Util.newLine}`*/
4487
4580
 
4488
4581
  break;
@@ -4561,6 +4654,7 @@ ${keys}.forEach(function (myobj, index) {
4561
4654
  /*
4562
4655
  MySQL CRUD with context
4563
4656
  */
4657
+
4564
4658
  zRoute.insertSQL = async (req, res, table, data) => {
4565
4659
  try {
4566
4660
  const MYMODELS = myCache.get("MYMODELS");
@@ -4578,7 +4672,9 @@ zRoute.insertSQL = async (req, res, table, data) => {
4578
4672
  delete data.approval_history;
4579
4673
 
4580
4674
  //check dropzone
4675
+ let movDropboxArr = [];
4581
4676
  let hasDropzone = false;
4677
+ let hasDropbox = false;
4582
4678
  for (let key in MYMODEL.widgets) {
4583
4679
  if (MYMODEL.widgets[key].name === "dropzone") {
4584
4680
  //console.log('has dropzone')
@@ -4604,13 +4700,75 @@ zRoute.insertSQL = async (req, res, table, data) => {
4604
4700
  data[key] = Util.array_to_jsonb(newArr);
4605
4701
  }
4606
4702
  }
4607
-
4608
4703
  //delete cache
4609
4704
  myCache.del(name);
4705
+ } else if (MYMODEL.widgets[key].name === "dropbox") {
4706
+ //console.log('has dropbox')
4707
+ let path_src = `/temps/${MYMODEL.table}/${key}/${userId}`;
4708
+ let path_dest = `/${MYMODEL.table}/${key}`;
4709
+
4710
+ // Initialize Dropbox client
4711
+ let dbx = new Dropbox({
4712
+ accessToken: process.env.DROPBOX_ACCESS_TOKEN,
4713
+ refreshToken: process.env.DROPBOX_REFRESH_TOKEN,
4714
+ clientId: process.env.DROPBOX_CLIENT_ID,
4715
+ clientSecret: process.env.DROPBOX_CLIENT_SECRET,
4716
+ fetch: fetch,
4717
+ });
4718
+
4719
+ try {
4720
+ await dbx.filesCreateFolderV2({
4721
+ path: path_dest,
4722
+ autorename: false,
4723
+ });
4724
+ } catch (error) {
4725
+ if (error.status !== 409) {
4726
+ // 409 means folder already exists
4727
+ throw error;
4728
+ }
4729
+ }
4730
+
4731
+ //get all files in folder
4732
+ //let files = await
4733
+ // First, move the file to the new location
4734
+ let name = `dropbox__${res.locals.userId}__${table}__${key}__create`;
4735
+ if (myCache.has(name)) {
4736
+ let arr = myCache.get(name);
4737
+ let newArr = [];
4738
+ if (arr.length > 0) {
4739
+ let time = new Date().getTime();
4740
+ arr.map(async (item) => {
4741
+ //check
4742
+ try {
4743
+ let newItem = Util.cleanString(time + item);
4744
+ movDropboxArr.push({
4745
+ from_path: `${path_src}/${item}`,
4746
+ to_path: `${path_dest}/${newItem}`,
4747
+ });
4748
+ /*await dbx.filesMoveV2({
4749
+ from_path: `${path_src}/${item}`,
4750
+ to_path: `${path_dest}/${newItem}`,
4751
+ autorename: true
4752
+ });*/
4753
+ newArr.push(newItem);
4754
+ } catch (e) {
4755
+ console.log(e);
4756
+ }
4757
+ });
4758
+ data[key] = Util.array_to_jsonb(newArr);
4759
+ }
4760
+ }
4761
+ myCache.del(name);
4610
4762
  }
4611
4763
  }
4612
4764
  const result = await connection.insert({ table: table, data: data });
4613
4765
  zRoute.modelsCacheRenew(table, res.locals.companyId);
4766
+ //dropbox
4767
+ if (movDropboxArr.length > 0) {
4768
+ setTimeout(function () {
4769
+ zRoute.moveDropbox(movDropboxArr);
4770
+ }, 3000);
4771
+ }
4614
4772
  return result;
4615
4773
  } catch (e) {
4616
4774
  throw Error(e + "");
@@ -4618,6 +4776,28 @@ zRoute.insertSQL = async (req, res, table, data) => {
4618
4776
  }
4619
4777
  };
4620
4778
 
4779
+ zRoute.moveDropbox = async (items) => {
4780
+ try {
4781
+ // Initialize Dropbox client
4782
+ let dbx = new Dropbox({
4783
+ accessToken: process.env.DROPBOX_ACCESS_TOKEN,
4784
+ refreshToken: process.env.DROPBOX_REFRESH_TOKEN,
4785
+ clientId: process.env.DROPBOX_CLIENT_ID,
4786
+ clientSecret: process.env.DROPBOX_CLIENT_SECRET,
4787
+ fetch: fetch,
4788
+ });
4789
+ for (item of items) {
4790
+ await dbx.filesMoveV2({
4791
+ from_path: item.from_path,
4792
+ to_path: item.to_path,
4793
+ autorename: true,
4794
+ });
4795
+ }
4796
+ } catch (e) {
4797
+ console.log(e);
4798
+ }
4799
+ };
4800
+
4621
4801
  zRoute.updateSQL = async (req, res, table, data, whereData) => {
4622
4802
  try {
4623
4803
  const MYMODELS = myCache.get("MYMODELS");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zet-lib",
3
- "version": "1.4.10",
3
+ "version": "1.4.12",
4
4
  "description": "zet is a library that part of zet generator.",
5
5
  "engines": {
6
6
  "node": ">=18"
@@ -31,25 +31,26 @@
31
31
  "axios": "^1.6.8",
32
32
  "convert-excel-to-json": "^1.7.0",
33
33
  "csurf": "^1.11.0",
34
- "dotenv": "^16.3.1",
34
+ "dotenv": "^16.5.0",
35
+ "dropbox": "^10.34.0",
35
36
  "ejs": "^3.1.9",
36
37
  "exceljs": "^4.4.0",
37
38
  "express-zip": "^3.0.0",
38
- "fs-extra": "^11.1.1",
39
+ "fs-extra": "^11.3.0",
39
40
  "html-minifier-terser": "^7.2.0",
41
+ "isomorphic-fetch": "^3.0.0",
40
42
  "js-sha256": "^0.9.0",
41
43
  "moment": "^2.30.1",
42
44
  "node-cache": "^5.1.2",
43
45
  "nodemailer": "^6.9.4",
44
46
  "pg": "^8.11.2",
45
47
  "pm2": "^5.3.1",
46
- "puppeteer": "^24.6.1",
48
+ "puppeteer": "^24.7.2",
47
49
  "qs": "^6.11.2",
48
50
  "randomstring": "^1.3.0",
49
51
  "read-excel-file": "^5.8.0",
50
52
  "sharp": "^0.34.1",
51
53
  "socket.io": "^4.8.0",
52
- "timers-promises": "^1.0.1",
53
54
  "uglify-js": "^3.17.4",
54
55
  "uuid": "^9.0.1",
55
56
  "xlsx": "^0.18.5"