@tenonhq/dovetail-dashboard 0.0.13 → 0.0.15

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tenonhq/dovetail-dashboard",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "description": "Update Set Dashboard for Dovetail",
5
5
  "main": "server.js",
6
6
  "scripts": {
@@ -9,10 +9,11 @@
9
9
  "postpublish": "npm run version:bump"
10
10
  },
11
11
  "dependencies": {
12
- "express": "^4.18.2",
13
12
  "axios": "^1.5.1",
14
13
  "axios-cookiejar-support": "^4.0.7",
14
+ "chokidar": "^3.6.0",
15
15
  "dotenv": "^16.3.1",
16
+ "express": "^4.18.2",
16
17
  "express-rate-limit": "^8.3.2",
17
18
  "tough-cookie": "^4.1.3"
18
19
  },
package/public/app.js CHANGED
@@ -860,13 +860,48 @@ var recentEditsInterval = null;
860
860
  async function loadRecentEdits() {
861
861
  try {
862
862
  var data = await api("GET", "/api/recent-edits");
863
- recentEdits = data.edits || [];
863
+ var incoming = data.edits || [];
864
+
865
+ // Warn if a newly-pushed file was already edited in the last 30 minutes
866
+ var THIRTY_MIN = 30 * 60 * 1000;
867
+ var now = Date.now();
868
+ incoming.forEach(function (edit) {
869
+ var alreadyPresent = recentEdits.some(function (prev) {
870
+ return prev.sys_id === edit.sys_id && prev.tableName === edit.tableName;
871
+ });
872
+ if (!alreadyPresent) {
873
+ var recentSave = recentEdits.some(function (prev) {
874
+ return (
875
+ prev.name === edit.name &&
876
+ prev.tableName === edit.tableName &&
877
+ now - new Date(prev.timestamp).getTime() < THIRTY_MIN
878
+ );
879
+ });
880
+ if (recentSave) {
881
+ toast(edit.name + " was already saved less than 30 minutes ago.", "warn");
882
+ }
883
+ }
884
+ });
885
+
886
+ recentEdits = incoming;
864
887
  renderRecentEdits();
865
888
  } catch (e) {
866
889
  // Silently fail — panel just stays hidden or stale
867
890
  }
868
891
  }
869
892
 
893
+ async function dismissRecentEdit(sys_id, tableName) {
894
+ try {
895
+ await api("POST", "/api/recent-edits/dismiss", { sys_id: sys_id, tableName: tableName });
896
+ recentEdits = recentEdits.filter(function (e) {
897
+ return !(e.sys_id === sys_id && e.tableName === tableName);
898
+ });
899
+ renderRecentEdits();
900
+ } catch (e) {
901
+ toast("Failed to dismiss: " + e.message, "error");
902
+ }
903
+ }
904
+
870
905
  function timeAgo(timestamp) {
871
906
  var now = new Date();
872
907
  var then = new Date(timestamp);
@@ -926,10 +961,21 @@ function renderRecentEdits() {
926
961
  timeEl.className = "recent-edit-time";
927
962
  timeEl.textContent = timeAgo(edit.timestamp);
928
963
 
964
+ var dismissBtn = document.createElement("button");
965
+ dismissBtn.className = "recent-edit-dismiss";
966
+ dismissBtn.title = "Dismiss";
967
+ dismissBtn.textContent = "×";
968
+ (function (id, table) {
969
+ dismissBtn.addEventListener("click", function () {
970
+ dismissRecentEdit(id, table);
971
+ });
972
+ })(edit.sys_id, edit.tableName);
973
+
929
974
  row.appendChild(nameEl);
930
975
  row.appendChild(scopeEl);
931
976
  row.appendChild(updateSetEl);
932
977
  row.appendChild(timeEl);
978
+ row.appendChild(dismissBtn);
933
979
  list.appendChild(row);
934
980
  });
935
981
  }