linguabot commited on
Commit
a584510
·
verified ·
1 Parent(s): 826aed7

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. client/src/components/Refinity.tsx +36 -12
client/src/components/Refinity.tsx CHANGED
@@ -51,6 +51,25 @@ type Task = {
51
  createdBy?: string;
52
  };
53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  const mockTasks: Task[] = [
55
  { id: 't1', title: 'Refinity Demo Task 1', sourceText: 'The quick brown fox jumps over the lazy dog.' },
56
  { id: 't2', title: 'Refinity Demo Task 2', sourceText: 'To be, or not to be, that is the question.' },
@@ -1106,13 +1125,14 @@ const Refinity: React.FC = () => {
1106
  data-btn="download"
1107
  onClick={(e)=>{
1108
  e.preventDefault(); e.stopPropagation();
1109
- // Export single version content as simple .docx (inline changes off)
1110
  (async()=>{
1111
  try {
1112
  const base = ((api.defaults as any)?.baseURL as string || '').replace(/\/$/, '');
1113
- const latestReviser = (v.revisedBy || v.originalAuthor || username || 'User');
1114
- const filename = `${(task?.title||'Task').replace(/[^\w\-\s]/g,'').replace(/\s+/g,'_')}_${(latestReviser||'User').replace(/[^\w\-\s]/g,'').replace(/\s+/g,'_')}_v${v.versionNumber}.docx`;
1115
- const resp = await fetch(`${base}/api/refinity/track-changes`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prev: '', current: v.content || '', filename }) });
 
1116
  if (!resp.ok) throw new Error('Export failed');
1117
  const blob = await resp.blob();
1118
  const url = window.URL.createObjectURL(blob);
@@ -1230,7 +1250,8 @@ const Refinity: React.FC = () => {
1230
  try {
1231
  const base = ((api.defaults as any)?.baseURL as string || '').replace(/\/$/, '');
1232
  const latestReviser = (b.revisedBy || b.originalAuthor || username || 'User');
1233
- const filename = `${(task?.title||'Task').replace(/[^\w\-\s]/g,'').replace(/\s+/g,'_')}_${(latestReviser||'User').replace(/[^\w\-\s]/g,'').replace(/\s+/g,'_')}_diff.docx`;
 
1234
  const body = { prev: a.content||'', current: b.content||'', filename, authorName: latestReviser };
1235
  const resp = await fetch(`${base}/api/refinity/track-changes-comments`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
1236
  if (!resp.ok) throw new Error('Export failed');
@@ -1248,7 +1269,8 @@ const Refinity: React.FC = () => {
1248
  try {
1249
  const base = ((api.defaults as any)?.baseURL as string || '').replace(/\/$/, '');
1250
  const latestReviser = (b.revisedBy || b.originalAuthor || username || 'User');
1251
- const filename = `${(task?.title||'Task').replace(/[^\w\-\s]/g,'').replace(/\s+/g,'_')}_${(latestReviser||'User').replace(/[^\w\-\s]/g,'').replace(/\s+/g,'_')}_ooxml.docx`;
 
1252
  const body = { prev: a.content||'', current: b.content||'', filename, authorName: latestReviser };
1253
  const resp = await fetch(`${base}/api/refinity/track-changes-ooxml`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
1254
  if (!resp.ok) throw new Error('Export failed');
@@ -1311,7 +1333,8 @@ const Refinity: React.FC = () => {
1311
  if (!a || !b || a.id===b.id) return;
1312
  const base = ((api.defaults as any)?.baseURL as string || '').replace(/\/$/, '');
1313
  const latestReviser = (b?.revisedBy || b?.originalAuthor || username || 'User');
1314
- const filename = `${(task?.title||'Task').replace(/[^\w\-\s]/g,'').replace(/\s+/g,'_')}_${(latestReviser||'User').replace(/[^\w\-\s]/g,'').replace(/\s+/g,'_')}_diff.docx`;
 
1315
  const body = { prev: (a.content||''), current: (b.content||''), filename, authorName: latestReviser };
1316
  const resp = await fetch(`${base}/api/refinity/track-changes-comments`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
1317
  if (!resp.ok) throw new Error('Export failed');
@@ -1328,7 +1351,8 @@ const Refinity: React.FC = () => {
1328
  if (!a || !b || a.id===b.id) return;
1329
  const base = ((api.defaults as any)?.baseURL as string || '').replace(/\/$/, '');
1330
  const latestReviser = (b?.revisedBy || b?.originalAuthor || username || 'User');
1331
- const filename = `${(task?.title||'Task').replace(/[^\w\-\s]/g,'').replace(/\s+/g,'_')}_${(latestReviser||'User').replace(/[^\w\-\s]/g,'').replace(/\s+/g,'_')}_ooxml.docx`;
 
1332
  const body = { prev: (a.content||''), current: (b.content||''), filename, authorName: latestReviser };
1333
  const resp = await fetch(`${base}/api/refinity/track-changes-ooxml`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
1334
  if (!resp.ok) throw new Error('Export failed');
@@ -1611,9 +1635,9 @@ const EditorPane: React.FC<{ source: string; initialTranslation: string; onBack:
1611
  try {
1612
  const base = ((api.defaults as any)?.baseURL as string || '').replace(/\/$/, '');
1613
  const taskNameSafe = (taskTitle || 'Task').replace(/[^\w\-\s]/g,'').replace(/\s+/g,'_');
1614
- const userNameSafe = (username || 'User').replace(/[^\w\-\s]/g,'').replace(/\s+/g,'_');
1615
  const vNum = `v${nextVersionNumber}`;
1616
- const filename = `${taskNameSafe}_${userNameSafe}_${vNum}.docx`;
1617
  const resp = await fetch(`${base}/api/refinity/track-changes`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prev: initialTranslation || '', current: text || '', filename }) });
1618
  if (!resp.ok) throw new Error('Export failed');
1619
  const blob = await resp.blob();
@@ -1739,8 +1763,8 @@ const EditorPane: React.FC<{ source: string; initialTranslation: string; onBack:
1739
  </button>
1740
  {revDownloadOpen && revMenuPos && createPortal(
1741
  <div style={{ position: 'fixed', left: revMenuPos.left, top: revMenuPos.top, zIndex: 10000, maxHeight: '240px', overflowY: 'auto' }} className="w-56 rounded-md border border-gray-200 bg-white shadow-lg text-left">
1742
- <button onClick={async()=>{ setRevDownloadOpen(false); try { const base=((api.defaults as any)?.baseURL as string||'').replace(/\/$/,''); const filename=`${(taskTitle||'Task').replace(/[^\w\-\s]/g,'').replace(/\s+/g,'_')}_${(username||'User').replace(/[^\w\-\s]/g,'').replace(/\s+/g,'_')}.docx`; const body={ current: text||'', filename }; const resp=await fetch(`${base}/api/refinity/export-plain`,{ method:'POST', headers:{ 'Content-Type':'application/json' }, body: JSON.stringify(body) }); if(!resp.ok) throw new Error('Export failed'); const blob=await resp.blob(); const url=window.URL.createObjectURL(blob); const link=document.createElement('a'); link.href=url; link.download=filename; document.body.appendChild(link); link.click(); link.remove(); window.URL.revokeObjectURL(url);} catch {} }} className="block w-full text-left px-3 py-2 text-sm hover:bg-gray-50">Without Annotations</button>
1743
- <button onClick={async()=>{ setRevDownloadOpen(false); try { const base=((api.defaults as any)?.baseURL as string||'').replace(/\/$/,''); const filename=`${(taskTitle||'Task').replace(/[^\w\-\s]/g,'').replace(/\s+/g,'_')}_${(username||'User').replace(/[^\w\-\s]/g,'').replace(/\s+/g,'_')}_annotated.docx`; const list=versionAnnotations.map(a=>({ start:a.start, end:a.end, category:a.category, comment:a.comment })); const body={ current: text||'', filename, annotations: list }; const resp=await fetch(`${base}/api/refinity/export-plain-with-annotations`,{ method:'POST', headers:{ 'Content-Type':'application/json' }, body: JSON.stringify(body) }); if(!resp.ok) throw new Error('Export failed'); const blob=await resp.blob(); const url=window.URL.createObjectURL(blob); const link=document.createElement('a'); link.href=url; link.download=filename; document.body.appendChild(link); link.click(); link.remove(); window.URL.revokeObjectURL(url);} catch {} }} className="block w-full text-left px-3 py-2 text-sm hover:bg-gray-50">With Annotations</button>
1744
  </div>, document.body
1745
  )}
1746
  </div>
 
51
  createdBy?: string;
52
  };
53
 
54
+ // ---- Filename helpers ----
55
+ function toSafeName(input: string): string {
56
+ return String(input || '')
57
+ .replace(/[^\w\-\s]/g, '')
58
+ .trim()
59
+ .replace(/\s+/g, '_');
60
+ }
61
+ function pad2(n: number): string {
62
+ return n < 10 ? `0${n}` : String(n);
63
+ }
64
+ function yyyymmdd_hhmm(d = new Date()): string {
65
+ const Y = d.getFullYear();
66
+ const M = pad2(d.getMonth() + 1);
67
+ const D = pad2(d.getDate());
68
+ const h = pad2(d.getHours());
69
+ const m = pad2(d.getMinutes());
70
+ return `${Y}${M}${D}_${h}${m}`;
71
+ }
72
+
73
  const mockTasks: Task[] = [
74
  { id: 't1', title: 'Refinity Demo Task 1', sourceText: 'The quick brown fox jumps over the lazy dog.' },
75
  { id: 't2', title: 'Refinity Demo Task 2', sourceText: 'To be, or not to be, that is the question.' },
 
1125
  data-btn="download"
1126
  onClick={(e)=>{
1127
  e.preventDefault(); e.stopPropagation();
1128
+ // Export single version content as plain .docx (same as Editor “Without Annotations”)
1129
  (async()=>{
1130
  try {
1131
  const base = ((api.defaults as any)?.baseURL as string || '').replace(/\/$/, '');
1132
+ const currentUser = username || 'User';
1133
+ const filename = `${toSafeName(task?.title||'Task')}_${yyyymmdd_hhmm()}_${toSafeName(currentUser)}.docx`;
1134
+ const body = { current: v.content || '', filename };
1135
+ const resp = await fetch(`${base}/api/refinity/export-plain`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
1136
  if (!resp.ok) throw new Error('Export failed');
1137
  const blob = await resp.blob();
1138
  const url = window.URL.createObjectURL(blob);
 
1250
  try {
1251
  const base = ((api.defaults as any)?.baseURL as string || '').replace(/\/$/, '');
1252
  const latestReviser = (b.revisedBy || b.originalAuthor || username || 'User');
1253
+ const A = a.versionNumber, B = b.versionNumber;
1254
+ const filename = `${toSafeName(task?.title||'Task')}_Compare-v${A}-v${B}_Inline_${yyyymmdd_hhmm()}_${toSafeName(latestReviser)}.docx`;
1255
  const body = { prev: a.content||'', current: b.content||'', filename, authorName: latestReviser };
1256
  const resp = await fetch(`${base}/api/refinity/track-changes-comments`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
1257
  if (!resp.ok) throw new Error('Export failed');
 
1269
  try {
1270
  const base = ((api.defaults as any)?.baseURL as string || '').replace(/\/$/, '');
1271
  const latestReviser = (b.revisedBy || b.originalAuthor || username || 'User');
1272
+ const A = a.versionNumber, B = b.versionNumber;
1273
+ const filename = `${toSafeName(task?.title||'Task')}_Compare-v${A}-v${B}_Comments_${yyyymmdd_hhmm()}_${toSafeName(latestReviser)}.docx`;
1274
  const body = { prev: a.content||'', current: b.content||'', filename, authorName: latestReviser };
1275
  const resp = await fetch(`${base}/api/refinity/track-changes-ooxml`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
1276
  if (!resp.ok) throw new Error('Export failed');
 
1333
  if (!a || !b || a.id===b.id) return;
1334
  const base = ((api.defaults as any)?.baseURL as string || '').replace(/\/$/, '');
1335
  const latestReviser = (b?.revisedBy || b?.originalAuthor || username || 'User');
1336
+ const A = a.versionNumber, B = b.versionNumber;
1337
+ const filename = `${toSafeName(task?.title||'Task')}_Compare-v${A}-v${B}_Inline_${yyyymmdd_hhmm()}_${toSafeName(latestReviser)}.docx`;
1338
  const body = { prev: (a.content||''), current: (b.content||''), filename, authorName: latestReviser };
1339
  const resp = await fetch(`${base}/api/refinity/track-changes-comments`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
1340
  if (!resp.ok) throw new Error('Export failed');
 
1351
  if (!a || !b || a.id===b.id) return;
1352
  const base = ((api.defaults as any)?.baseURL as string || '').replace(/\/$/, '');
1353
  const latestReviser = (b?.revisedBy || b?.originalAuthor || username || 'User');
1354
+ const A = a.versionNumber, B = b.versionNumber;
1355
+ const filename = `${toSafeName(task?.title||'Task')}_Compare-v${A}-v${B}_Comments_${yyyymmdd_hhmm()}_${toSafeName(latestReviser)}.docx`;
1356
  const body = { prev: (a.content||''), current: (b.content||''), filename, authorName: latestReviser };
1357
  const resp = await fetch(`${base}/api/refinity/track-changes-ooxml`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
1358
  if (!resp.ok) throw new Error('Export failed');
 
1635
  try {
1636
  const base = ((api.defaults as any)?.baseURL as string || '').replace(/\/$/, '');
1637
  const taskNameSafe = (taskTitle || 'Task').replace(/[^\w\-\s]/g,'').replace(/\s+/g,'_');
1638
+ const userNameSafe = toSafeName(username || 'User');
1639
  const vNum = `v${nextVersionNumber}`;
1640
+ const filename = `${taskNameSafe}_${vNum}_Clean_${yyyymmdd_hhmm()}_${userNameSafe}.docx`;
1641
  const resp = await fetch(`${base}/api/refinity/track-changes`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prev: initialTranslation || '', current: text || '', filename }) });
1642
  if (!resp.ok) throw new Error('Export failed');
1643
  const blob = await resp.blob();
 
1763
  </button>
1764
  {revDownloadOpen && revMenuPos && createPortal(
1765
  <div style={{ position: 'fixed', left: revMenuPos.left, top: revMenuPos.top, zIndex: 10000, maxHeight: '240px', overflowY: 'auto' }} className="w-56 rounded-md border border-gray-200 bg-white shadow-lg text-left">
1766
+ <button onClick={async()=>{ setRevDownloadOpen(false); try { const base=((api.defaults as any)?.baseURL as string||'').replace(/\/$/,''); const filename=`${toSafeName(taskTitle||'Task')}_${yyyymmdd_hhmm()}_${toSafeName(username||'User')}.docx`; const body={ current: text||'', filename }; const resp=await fetch(`${base}/api/refinity/export-plain`,{ method:'POST', headers:{ 'Content-Type':'application/json' }, body: JSON.stringify(body) }); if(!resp.ok) throw new Error('Export failed'); const blob=await resp.blob(); const url=window.URL.createObjectURL(blob); const link=document.createElement('a'); link.href=url; link.download=filename; document.body.appendChild(link); link.click(); link.remove(); window.URL.revokeObjectURL(url);} catch {} }} className="block w-full text-left px-3 py-2 text-sm hover:bg-gray-50">Without Annotations</button>
1767
+ <button onClick={async()=>{ setRevDownloadOpen(false); try { const base=((api.defaults as any)?.baseURL as string||'').replace(/\/$/,''); const filename=`${toSafeName(taskTitle||'Task')}_v${nextVersionNumber}_Annotated_${yyyymmdd_hhmm()}_${toSafeName(username||'User')}.docx`; const list=versionAnnotations.map(a=>({ start:a.start, end:a.end, category:a.category, comment:a.comment })); const body={ current: text||'', filename, annotations: list }; const resp=await fetch(`${base}/api/refinity/export-plain-with-annotations`,{ method:'POST', headers:{ 'Content-Type':'application/json' }, body: JSON.stringify(body) }); if(!resp.ok) throw new Error('Export failed'); const blob=await resp.blob(); const url=window.URL.createObjectURL(blob); const link=document.createElement('a'); link.href=url; link.download=filename; document.body.appendChild(link); link.click(); link.remove(); window.URL.revokeObjectURL(url);} catch {} }} className="block w-full text-left px-3 py-2 text-sm hover:bg-gray-50">With Annotations</button>
1768
  </div>, document.body
1769
  )}
1770
  </div>