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