gramene-search 2.7.0 → 2.8.0

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/dist/index.js CHANGED
@@ -12504,7 +12504,7 @@ var $261baeb81c4d4d8a$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.conn
12504
12504
 
12505
12505
 
12506
12506
  const $0f50f369018a42ef$var$MAX_GENE_IDS = 1000; // Define the maximum number of gene IDs allowed
12507
- const $0f50f369018a42ef$var$formatCreatedAt = (value)=>{
12507
+ const $0f50f369018a42ef$var$formatDate = (value)=>{
12508
12508
  if (!value) return '';
12509
12509
  const d = new Date(value);
12510
12510
  if (isNaN(d.getTime())) return '';
@@ -12517,7 +12517,7 @@ const $0f50f369018a42ef$var$applySortFilter = (lists, search, sort)=>{
12517
12517
  const mult = dir === 'asc' ? 1 : -1;
12518
12518
  result.sort((a, b)=>{
12519
12519
  let av = a[key], bv = b[key];
12520
- if (key === 'createdAt') {
12520
+ if (key === 'createdAt' || key === 'deletedAt') {
12521
12521
  av = av ? new Date(av).getTime() : 0;
12522
12522
  bv = bv ? new Date(bv).getTime() : 0;
12523
12523
  } else if (key === 'n_genes') {
@@ -12564,16 +12564,18 @@ const $0f50f369018a42ef$var$GeneListDisplayComponent = (props)=>{
12564
12564
  const [error, setError] = (0, $gXNCa$react.useState)(null);
12565
12565
  const [notice, setNotice] = (0, $gXNCa$react.useState)(null);
12566
12566
  const [user, setUser] = (0, $gXNCa$react.useState)({});
12567
+ const [viewMode, setViewMode] = (0, $gXNCa$react.useState)('active'); // 'active' | 'trash'
12567
12568
  const [editingId, setEditingId] = (0, $gXNCa$react.useState)(null);
12568
12569
  const [editLabel, setEditLabel] = (0, $gXNCa$react.useState)('');
12569
12570
  const [editIsPublic, setEditIsPublic] = (0, $gXNCa$react.useState)(false);
12570
- const [deleteTarget, setDeleteTarget] = (0, $gXNCa$react.useState)(null);
12571
+ const [deleteTarget, setDeleteTarget] = (0, $gXNCa$react.useState)(null); // { list, permanent }
12571
12572
  const [search, setSearch] = (0, $gXNCa$react.useState)('');
12572
12573
  const [sort, setSort] = (0, $gXNCa$react.useState)({
12573
12574
  key: 'createdAt',
12574
12575
  dir: 'desc'
12575
12576
  });
12576
12577
  const auth = props.auth;
12578
+ const isTrash = viewMode === 'trash';
12577
12579
  (0, $gXNCa$react.useEffect)(()=>{
12578
12580
  if (!auth) return;
12579
12581
  const unsubscribe = (0, $gXNCa$firebaseauth.onAuthStateChanged)(auth, (u)=>setUser(u));
@@ -12605,7 +12607,9 @@ const $0f50f369018a42ef$var$GeneListDisplayComponent = (props)=>{
12605
12607
  search,
12606
12608
  sort
12607
12609
  ]);
12608
- const fetchPrivateGeneLists = async ()=>{
12610
+ // includeDeleted: 'active' (default) or 'trash'. Trash is auth-only and holds
12611
+ // the caller's own soft-deleted lists (restorable for 30 days).
12612
+ const fetchPrivateGeneLists = async (includeDeleted = 'active')=>{
12609
12613
  if (!auth) {
12610
12614
  setPrivateGeneLists([]);
12611
12615
  setError(null);
@@ -12615,12 +12619,12 @@ const $0f50f369018a42ef$var$GeneListDisplayComponent = (props)=>{
12615
12619
  if (!user || typeof user.getIdToken !== 'function') {
12616
12620
  setPrivateGeneLists([]);
12617
12621
  setError(null);
12618
- setNotice('Log in to create and manage your personal gene lists.');
12622
+ setNotice(includeDeleted === 'trash' ? 'Log in to view your deleted gene lists.' : 'Log in to create and manage your personal gene lists.');
12619
12623
  return;
12620
12624
  }
12621
12625
  try {
12622
12626
  const token = await user.getIdToken();
12623
- const response = await fetch(`${props.api}/gene_lists?site=${props.site}&isPublic=false`, {
12627
+ const response = await fetch(`${props.api}/gene_lists?site=${props.site}&isPublic=false&includeDeleted=${includeDeleted}`, {
12624
12628
  method: 'GET',
12625
12629
  headers: {
12626
12630
  "Content-Type": "application/json",
@@ -12630,26 +12634,61 @@ const $0f50f369018a42ef$var$GeneListDisplayComponent = (props)=>{
12630
12634
  const result = await response.json();
12631
12635
  if (response.ok) {
12632
12636
  setError(null);
12633
- setNotice(null);
12637
+ // Keep any restore/delete notice; only clear the "log in" prompt.
12638
+ setNotice((n)=>n && /Log in/.test(n) ? null : n);
12634
12639
  setPrivateGeneLists(result);
12635
12640
  } else setError('Error fetching gene lists.');
12636
12641
  } catch (err) {
12637
12642
  setError('Failed to fetch private gene lists. Please try again later.');
12638
12643
  }
12639
12644
  };
12640
- // Fetch saved gene lists from a backend or local storage
12645
+ // Public lists are always active (soft-deleted lists are never public-visible;
12646
+ // the trash view is caller-scoped).
12641
12647
  const fetchPublicGeneLists = async ()=>{
12642
12648
  try {
12643
- // Replace this with actual fetch from your backend or storage
12644
12649
  const response = await fetch(`${props.api}/gene_lists?site=${props.site}&isPublic=true`);
12645
12650
  const result = await response.json();
12646
- if (response.ok) setPublicGeneLists(result); // array of saved gene lists
12651
+ if (response.ok) setPublicGeneLists(result);
12647
12652
  else setError('Error fetching gene lists.');
12648
12653
  } catch (err) {
12649
12654
  setError('Failed to fetch gene lists. Please try again later.');
12650
12655
  }
12651
12656
  };
12652
- // Example functions for viewing and deleting lists
12657
+ const refresh = ()=>{
12658
+ if (isTrash) {
12659
+ setPublicGeneLists([]);
12660
+ fetchPrivateGeneLists('trash');
12661
+ } else {
12662
+ fetchPublicGeneLists();
12663
+ fetchPrivateGeneLists('active');
12664
+ }
12665
+ };
12666
+ // Fetch when the user, view mode, or an external save (refreshKey) changes.
12667
+ (0, $gXNCa$react.useEffect)(()=>{
12668
+ refresh();
12669
+ // eslint-disable-next-line react-hooks/exhaustive-deps
12670
+ }, [
12671
+ user,
12672
+ viewMode,
12673
+ props.refreshKey
12674
+ ]);
12675
+ // A logged-out user has no trash; fall back to the active (public) view.
12676
+ (0, $gXNCa$react.useEffect)(()=>{
12677
+ if (!currentUid && isTrash) setViewMode('active');
12678
+ }, [
12679
+ currentUid,
12680
+ isTrash
12681
+ ]);
12682
+ const switchView = (mode)=>{
12683
+ setViewMode(mode);
12684
+ setEditingId(null);
12685
+ setSearch('');
12686
+ setNotice(null);
12687
+ setSort({
12688
+ key: mode === 'trash' ? 'deletedAt' : 'createdAt',
12689
+ dir: 'desc'
12690
+ });
12691
+ };
12653
12692
  const viewGeneList = (list)=>{
12654
12693
  props.addFilter({
12655
12694
  category: 'Gene List',
@@ -12685,8 +12724,7 @@ const $0f50f369018a42ef$var$GeneListDisplayComponent = (props)=>{
12685
12724
  if (response.ok) {
12686
12725
  cancelEdit();
12687
12726
  setError(null);
12688
- await fetchPrivateGeneLists();
12689
- await fetchPublicGeneLists();
12727
+ refresh();
12690
12728
  } else if (response.status === 401) setError('You must be signed in to edit a gene list.');
12691
12729
  else if (response.status === 404) setError('Gene list not found or you do not own it.');
12692
12730
  else if (response.status === 400) setError("Nothing to update \u2014 please enter a label.");
@@ -12695,219 +12733,272 @@ const $0f50f369018a42ef$var$GeneListDisplayComponent = (props)=>{
12695
12733
  setError('Failed to update gene list.');
12696
12734
  }
12697
12735
  };
12698
- const requestDelete = (list)=>setDeleteTarget(list);
12736
+ const restoreList = async (list)=>{
12737
+ try {
12738
+ const token = await user.getIdToken();
12739
+ const response = await fetch(`${props.api}/gene_lists/restore?listId=${encodeURIComponent(list._id)}`, {
12740
+ method: 'POST',
12741
+ headers: {
12742
+ "Content-Type": "application/json",
12743
+ "Authorization": `Bearer ${token}`
12744
+ }
12745
+ });
12746
+ if (response.ok) {
12747
+ setError(null);
12748
+ setNotice(`Restored \u{201C}${list.label}\u{201D}.`);
12749
+ refresh();
12750
+ } else if (response.status === 404) setError('This list has been purged and can no longer be restored.');
12751
+ else if (response.status === 401) setError('You must be signed in to restore a gene list.');
12752
+ else setError('Failed to restore gene list.');
12753
+ } catch (err) {
12754
+ setError('Failed to restore gene list.');
12755
+ }
12756
+ };
12757
+ const requestDelete = (list, permanent)=>setDeleteTarget({
12758
+ list: list,
12759
+ permanent: !!permanent
12760
+ });
12699
12761
  const cancelDelete = ()=>setDeleteTarget(null);
12762
+ // Default DELETE is a soft delete (moves to trash, restorable 30 days).
12763
+ // `force=true` permanently removes it (offered from the trash view).
12700
12764
  const confirmDelete = async ()=>{
12701
12765
  if (!deleteTarget) return;
12702
- const listId = deleteTarget._id;
12766
+ const { list: list, permanent: permanent } = deleteTarget;
12703
12767
  setDeleteTarget(null);
12704
12768
  try {
12705
12769
  const token = await user.getIdToken();
12706
- const response = await fetch(`${props.api}/gene_lists?listId=${encodeURIComponent(listId)}`, {
12770
+ const url = `${props.api}/gene_lists?listId=${encodeURIComponent(list._id)}${permanent ? '&force=true' : ''}`;
12771
+ const response = await fetch(url, {
12707
12772
  method: 'DELETE',
12708
12773
  headers: {
12709
12774
  "Authorization": `Bearer ${token}`
12710
12775
  }
12711
12776
  });
12712
12777
  if (response.ok) {
12713
- await fetchPrivateGeneLists();
12714
- await fetchPublicGeneLists();
12715
- } else if (response.status === 401) alert('You must be signed in to delete a gene list.');
12716
- else if (response.status === 404) alert('Gene list not found or you do not own it.');
12717
- else alert('Failed to delete gene list.');
12778
+ setError(null);
12779
+ setNotice(permanent ? `Permanently deleted \u{201C}${list.label}\u{201D}.` : `Moved \u{201C}${list.label}\u{201D} to trash \u{2014} restore within 30 days from the Trash tab.`);
12780
+ refresh();
12781
+ } else if (response.status === 401) setError('You must be signed in to delete a gene list.');
12782
+ else if (response.status === 404) setError('Gene list not found or you do not own it.');
12783
+ else setError('Failed to delete gene list.');
12718
12784
  } catch (err) {
12719
- alert('Failed to delete gene list.');
12785
+ setError('Failed to delete gene list.');
12720
12786
  }
12721
12787
  };
12722
- // Fetch data when the component is mounted or after a save
12723
- (0, $gXNCa$react.useEffect)(()=>{
12724
- fetchPublicGeneLists();
12725
- }, [
12726
- props.refreshKey
12727
- ]);
12728
- (0, $gXNCa$react.useEffect)(()=>{
12729
- fetchPrivateGeneLists();
12730
- }, [
12731
- user,
12732
- props.refreshKey
12733
- ]);
12788
+ const dateKey = isTrash ? 'deletedAt' : 'createdAt';
12789
+ const dateLabel = isTrash ? 'Deleted' : 'Created';
12734
12790
  return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
12735
12791
  className: "gene-list-display-component",
12736
12792
  children: [
12737
12793
  error && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Alert), {
12738
12794
  variant: "danger",
12795
+ onClose: ()=>setError(null),
12796
+ dismissible: true,
12739
12797
  children: error
12740
12798
  }),
12741
12799
  notice && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Alert), {
12742
12800
  variant: "info",
12801
+ onClose: ()=>setNotice(null),
12802
+ dismissible: true,
12743
12803
  children: notice
12744
12804
  }),
12745
- mergedLists.length > 0 ? /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
12746
- className: "mt-4",
12805
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
12806
+ className: "d-flex justify-content-between align-items-center mb-2 mt-4",
12747
12807
  children: [
12748
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
12749
- className: "d-flex justify-content-end mb-2",
12750
- children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Form).Control, {
12751
- type: "search",
12752
- placeholder: "Search...",
12753
- value: search,
12754
- onChange: (e)=>setSearch(e.target.value),
12755
- style: {
12756
- maxWidth: 220
12757
- },
12758
- size: "sm"
12759
- })
12808
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.ButtonGroup), {
12809
+ size: "sm",
12810
+ children: [
12811
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
12812
+ variant: !isTrash ? 'primary' : 'outline-secondary',
12813
+ onClick: ()=>switchView('active'),
12814
+ children: "Active"
12815
+ }),
12816
+ currentUid && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
12817
+ variant: isTrash ? 'primary' : 'outline-secondary',
12818
+ onClick: ()=>switchView('trash'),
12819
+ children: "Trash"
12820
+ })
12821
+ ]
12760
12822
  }),
12761
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
12823
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Form).Control, {
12824
+ type: "search",
12825
+ placeholder: "Search...",
12826
+ value: search,
12827
+ onChange: (e)=>setSearch(e.target.value),
12762
12828
  style: {
12763
- maxHeight: 500,
12764
- overflowY: 'auto',
12765
- border: '1px solid #dee2e6',
12766
- borderRadius: 4
12829
+ maxWidth: 220
12767
12830
  },
12768
- children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.Table), {
12769
- striped: true,
12770
- hover: true,
12771
- className: "mb-0",
12772
- children: [
12773
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("thead", {
12774
- children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("tr", {
12775
- children: [
12776
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($0f50f369018a42ef$var$SortHeader, {
12777
- label: "List Name",
12778
- sortKey: "label",
12779
- sort: sort,
12780
- onToggle: toggleSort
12781
- }),
12782
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($0f50f369018a42ef$var$SortHeader, {
12783
- label: "Owner",
12784
- sortKey: "owner",
12785
- sort: sort,
12786
- onToggle: toggleSort
12787
- }),
12788
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($0f50f369018a42ef$var$SortHeader, {
12789
- label: "Genes",
12790
- sortKey: "n_genes",
12791
- sort: sort,
12792
- onToggle: toggleSort
12793
- }),
12794
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($0f50f369018a42ef$var$SortHeader, {
12795
- label: "Created",
12796
- sortKey: "createdAt",
12797
- sort: sort,
12798
- onToggle: toggleSort
12799
- }),
12800
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("th", {
12801
- style: $0f50f369018a42ef$var$stickyHeaderStyle,
12802
- children: "Actions"
12803
- })
12804
- ]
12831
+ size: "sm"
12832
+ })
12833
+ ]
12834
+ }),
12835
+ mergedLists.length > 0 ? /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
12836
+ style: {
12837
+ maxHeight: 500,
12838
+ overflowY: 'auto',
12839
+ border: '1px solid #dee2e6',
12840
+ borderRadius: 4
12841
+ },
12842
+ children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.Table), {
12843
+ striped: true,
12844
+ hover: true,
12845
+ className: "mb-0",
12846
+ children: [
12847
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("thead", {
12848
+ children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("tr", {
12849
+ children: [
12850
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($0f50f369018a42ef$var$SortHeader, {
12851
+ label: "List Name",
12852
+ sortKey: "label",
12853
+ sort: sort,
12854
+ onToggle: toggleSort
12855
+ }),
12856
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($0f50f369018a42ef$var$SortHeader, {
12857
+ label: "Owner",
12858
+ sortKey: "owner",
12859
+ sort: sort,
12860
+ onToggle: toggleSort
12861
+ }),
12862
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($0f50f369018a42ef$var$SortHeader, {
12863
+ label: "Genes",
12864
+ sortKey: "n_genes",
12865
+ sort: sort,
12866
+ onToggle: toggleSort
12867
+ }),
12868
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($0f50f369018a42ef$var$SortHeader, {
12869
+ label: dateLabel,
12870
+ sortKey: dateKey,
12871
+ sort: sort,
12872
+ onToggle: toggleSort
12873
+ }),
12874
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("th", {
12875
+ style: $0f50f369018a42ef$var$stickyHeaderStyle,
12876
+ children: "Actions"
12805
12877
  })
12806
- }),
12807
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("tbody", {
12808
- children: displayedLists.map((list, index)=>{
12809
- const isMine = currentUid && list.uid === currentUid;
12810
- const ownerLabel = isMine ? 'You' : list.owner || 'Unknown';
12811
- return editingId === list._id ? /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("tr", {
12878
+ ]
12879
+ })
12880
+ }),
12881
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("tbody", {
12882
+ children: displayedLists.map((list, index)=>{
12883
+ const isMine = currentUid && list.uid === currentUid;
12884
+ const ownerLabel = isMine ? 'You' : list.owner || 'Unknown';
12885
+ const dateVal = $0f50f369018a42ef$var$formatDate(isTrash ? list.deletedAt : list.createdAt);
12886
+ return !isTrash && editingId === list._id ? /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("tr", {
12887
+ children: [
12888
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("td", {
12812
12889
  children: [
12813
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("td", {
12814
- children: [
12815
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Form).Control, {
12816
- type: "text",
12817
- value: editLabel,
12818
- onChange: (e)=>setEditLabel(e.target.value),
12819
- placeholder: "List name"
12820
- }),
12821
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Form).Check, {
12822
- type: "switch",
12823
- id: `edit-public-${list._id}`,
12824
- label: "Public",
12825
- checked: editIsPublic,
12826
- onChange: ()=>setEditIsPublic(!editIsPublic),
12827
- className: "mt-2"
12828
- })
12829
- ]
12830
- }),
12831
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
12832
- children: ownerLabel
12833
- }),
12834
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
12835
- children: list.n_genes || 0
12836
- }),
12837
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
12838
- children: $0f50f369018a42ef$var$formatCreatedAt(list.createdAt)
12890
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Form).Control, {
12891
+ type: "text",
12892
+ value: editLabel,
12893
+ onChange: (e)=>setEditLabel(e.target.value),
12894
+ placeholder: "List name"
12839
12895
  }),
12840
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("td", {
12841
- children: [
12842
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
12843
- variant: "primary",
12844
- size: "sm",
12845
- onClick: ()=>saveEdit(list._id),
12846
- children: "Save"
12847
- }),
12848
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
12849
- variant: "outline-secondary",
12850
- size: "sm",
12851
- onClick: cancelEdit,
12852
- className: "ml-2",
12853
- children: "Cancel"
12854
- })
12855
- ]
12896
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Form).Check, {
12897
+ type: "switch",
12898
+ id: `edit-public-${list._id}`,
12899
+ label: "Public",
12900
+ checked: editIsPublic,
12901
+ onChange: ()=>setEditIsPublic(!editIsPublic),
12902
+ className: "mt-2"
12856
12903
  })
12857
12904
  ]
12858
- }, index) : /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("tr", {
12905
+ }),
12906
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
12907
+ children: ownerLabel
12908
+ }),
12909
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
12910
+ children: list.n_genes || 0
12911
+ }),
12912
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
12913
+ children: dateVal
12914
+ }),
12915
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("td", {
12859
12916
  children: [
12860
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("td", {
12861
- children: [
12862
- list.label,
12863
- list.isPublic ? ' (public)' : ''
12864
- ]
12865
- }),
12866
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
12867
- children: ownerLabel
12868
- }),
12869
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
12870
- children: list.n_genes || 0
12871
- }),
12872
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
12873
- children: $0f50f369018a42ef$var$formatCreatedAt(list.createdAt)
12917
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
12918
+ variant: "primary",
12919
+ size: "sm",
12920
+ onClick: ()=>saveEdit(list._id),
12921
+ children: "Save"
12874
12922
  }),
12875
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("td", {
12876
- children: [
12877
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
12878
- variant: "outline-secondary",
12879
- size: "sm",
12880
- onClick: ()=>viewGeneList(list),
12881
- children: "View"
12882
- }),
12883
- isMine && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
12884
- variant: "outline-secondary",
12885
- size: "sm",
12886
- onClick: ()=>startEdit(list),
12887
- className: "ml-2",
12888
- children: "Edit"
12889
- }),
12890
- isMine && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
12891
- variant: "outline-danger",
12892
- size: "sm",
12893
- onClick: ()=>requestDelete(list),
12894
- className: "ml-2",
12895
- children: "Delete"
12896
- })
12897
- ]
12923
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
12924
+ variant: "outline-secondary",
12925
+ size: "sm",
12926
+ onClick: cancelEdit,
12927
+ className: "ml-2",
12928
+ children: "Cancel"
12898
12929
  })
12899
12930
  ]
12900
- }, index);
12901
- })
12902
- })
12903
- ]
12931
+ })
12932
+ ]
12933
+ }, index) : /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("tr", {
12934
+ children: [
12935
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("td", {
12936
+ children: [
12937
+ list.label,
12938
+ list.isPublic ? ' (public)' : ''
12939
+ ]
12940
+ }),
12941
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
12942
+ children: ownerLabel
12943
+ }),
12944
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
12945
+ children: list.n_genes || 0
12946
+ }),
12947
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
12948
+ children: dateVal
12949
+ }),
12950
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
12951
+ children: isTrash ? isMine && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactjsxruntime.Fragment), {
12952
+ children: [
12953
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
12954
+ variant: "outline-success",
12955
+ size: "sm",
12956
+ onClick: ()=>restoreList(list),
12957
+ children: "Restore"
12958
+ }),
12959
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
12960
+ variant: "outline-danger",
12961
+ size: "sm",
12962
+ onClick: ()=>requestDelete(list, true),
12963
+ className: "ml-2",
12964
+ children: "Delete forever"
12965
+ })
12966
+ ]
12967
+ }) : /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactjsxruntime.Fragment), {
12968
+ children: [
12969
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
12970
+ variant: "outline-secondary",
12971
+ size: "sm",
12972
+ onClick: ()=>viewGeneList(list),
12973
+ children: "View"
12974
+ }),
12975
+ isMine && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
12976
+ variant: "outline-secondary",
12977
+ size: "sm",
12978
+ onClick: ()=>startEdit(list),
12979
+ className: "ml-2",
12980
+ children: "Edit"
12981
+ }),
12982
+ isMine && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
12983
+ variant: "outline-danger",
12984
+ size: "sm",
12985
+ onClick: ()=>requestDelete(list, false),
12986
+ className: "ml-2",
12987
+ children: "Delete"
12988
+ })
12989
+ ]
12990
+ })
12991
+ })
12992
+ ]
12993
+ }, index);
12994
+ })
12904
12995
  })
12905
- })
12906
- ]
12996
+ ]
12997
+ })
12907
12998
  }) : /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Alert), {
12908
12999
  variant: "warning",
12909
- className: "mt-4",
12910
- children: "No saved gene lists found."
13000
+ className: "mt-2",
13001
+ children: isTrash ? 'Trash is empty.' : 'No saved gene lists found.'
12911
13002
  }),
12912
13003
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.Modal), {
12913
13004
  show: !!deleteTarget,
@@ -12917,22 +13008,29 @@ const $0f50f369018a42ef$var$GeneListDisplayComponent = (props)=>{
12917
13008
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Modal).Header, {
12918
13009
  closeButton: true,
12919
13010
  children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Modal).Title, {
12920
- children: "Delete gene list?"
13011
+ children: deleteTarget && deleteTarget.permanent ? 'Permanently delete gene list?' : 'Move gene list to trash?'
12921
13012
  })
12922
13013
  }),
12923
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.Modal).Body, {
12924
- children: [
12925
- "Are you sure you want to delete",
12926
- deleteTarget ? /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactjsxruntime.Fragment), {
12927
- children: [
12928
- " ",
12929
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("strong", {
12930
- children: deleteTarget.label
12931
- })
12932
- ]
12933
- }) : ' this gene list',
12934
- "? This action cannot be undone."
12935
- ]
13014
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Modal).Body, {
13015
+ children: deleteTarget && deleteTarget.permanent ? /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactjsxruntime.Fragment), {
13016
+ children: [
13017
+ "Permanently delete ",
13018
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("strong", {
13019
+ children: deleteTarget.list.label
13020
+ }),
13021
+ "? This cannot be undone."
13022
+ ]
13023
+ }) : /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactjsxruntime.Fragment), {
13024
+ children: [
13025
+ "Move ",
13026
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("strong", {
13027
+ children: deleteTarget ? deleteTarget.list.label : 'this list'
13028
+ }),
13029
+ " to trash?",
13030
+ ' ',
13031
+ "You can restore it within 30 days from the Trash tab."
13032
+ ]
13033
+ })
12936
13034
  }),
12937
13035
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.Modal).Footer, {
12938
13036
  children: [
@@ -12945,7 +13043,7 @@ const $0f50f369018a42ef$var$GeneListDisplayComponent = (props)=>{
12945
13043
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
12946
13044
  variant: "danger",
12947
13045
  onClick: confirmDelete,
12948
- children: "Delete"
13046
+ children: deleteTarget && deleteTarget.permanent ? 'Delete forever' : 'Move to trash'
12949
13047
  })
12950
13048
  ]
12951
13049
  })
@@ -13163,6 +13261,7 @@ const $0f50f369018a42ef$var$GeneListComponent = (props)=>{
13163
13261
  type: "switch",
13164
13262
  id: "listIsPublic",
13165
13263
  label: "Public",
13264
+ checked: listIsPublic,
13166
13265
  onChange: (e)=>setListIsPublic(!listIsPublic)
13167
13266
  })
13168
13267
  ]