From 90c259deb564d50fb3bf65f322e96a793f5b2b3e Mon Sep 17 00:00:00 2001 From: Nicholas Lee Date: Wed, 10 Apr 2024 16:45:06 -0400 Subject: [PATCH] 198 add publicprivate button for user owned studiesdatasetsannotations (#751) * feat: update react router * feat: added readonly annotations table and project owner * add spaces * [ENH] allow "post" to annotation-analysis endpoint (#742) * allow "post" to annotation-analysis endpoint * fix f string * test more and fix formatting * update openapi to main * [FIX] match input study by either doi and/or pmid (#744) * match input study by either doi and/or pmid * black * fix: e2e tests * fix: update openapi version * fix: sdk update * fix: correct sdk version * fix: openapi version * chore: add tests for public private button * fix: resolve merge conflicts * feat: better loading text support * fix: update codespell * chore: remove only warn for codespell * fix: added back exclude glob * fix: try singlequote * fix: try again --------- Co-authored-by: James Kent --- .github/workflows/codespell.yml | 2 + .../cypress/e2e/pages/ProjectPage.cy.tsx | 36 +- .../cypress/fixtures/projects/projectPut.json | 711 ++++++++++++++++++ .../src/components/TextEdit/TextEdit.tsx | 2 +- .../CurationPage/ProjectIsLoadingText.tsx | 52 +- .../MetaAnalysisPage/MetaAnalysisPage.tsx | 2 +- .../Projects/ProjectPage/ProjectPage.tsx | 125 ++- .../Projects/ProjectPage/ProjectStore.ts | 35 +- 8 files changed, 905 insertions(+), 60 deletions(-) create mode 100644 compose/neurosynth-frontend/cypress/fixtures/projects/projectPut.json diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index 685121440..fdc48d0b3 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -20,3 +20,5 @@ jobs: uses: actions/checkout@v4 - name: Codespell uses: codespell-project/actions-codespell@master + with: + exclude_file: compose/neurosynth-frontend/cypress/fixtures/*.json \ No newline at end of file diff --git a/compose/neurosynth-frontend/cypress/e2e/pages/ProjectPage.cy.tsx b/compose/neurosynth-frontend/cypress/e2e/pages/ProjectPage.cy.tsx index 5b2e4dbe1..57e084bef 100644 --- a/compose/neurosynth-frontend/cypress/e2e/pages/ProjectPage.cy.tsx +++ b/compose/neurosynth-frontend/cypress/e2e/pages/ProjectPage.cy.tsx @@ -9,13 +9,45 @@ describe(PAGE_NAME, () => { beforeEach(() => { cy.clearLocalStorage().clearSessionStorage(); cy.intercept('GET', 'https://api.appzi.io/**', { fixture: 'appzi' }).as('appziFixture'); + cy.intercept('GET', `**/api/studysets/*`, { fixture: 'studyset' }).as('studysetFixture'); + cy.intercept('PUT', `**/api/projects/*`, { fixture: 'projects/projectPut' }).as( + 'updateProjectFixture' + ); + }); + + it('should load successfully', () => { cy.intercept('GET', `**/api/projects/*`, { fixture: 'projects/projectExtractionStep' }).as( 'projectFixture' ); - cy.intercept('GET', `**/api/studysets/*`, { fixture: 'studyset' }).as('studysetFixture'); + cy.visit(PATH).wait('@projectFixture'); }); - it('should load successfully', () => { + it('should set the project from private to public', () => { + cy.intercept('GET', `**/api/projects/*`, { fixture: 'projects/projectExtractionStep' }).as( + 'projectFixture' + ); cy.visit(PATH).wait('@projectFixture'); + cy.contains('button', 'Public').click(); + cy.wait('@updateProjectFixture').then((res) => { + assert.exists(res.request.body.public); + assert.isTrue(res.request.body.public); + }); + }); + + it.only('should set the project from public to private', () => { + cy.fixture('projects/projectExtractionStep').then((projectFixture) => { + projectFixture.public = true; + cy.intercept('GET', `**/api/projects/*`, projectFixture).as('projectFixturePublic'); + }); + cy.visit(PATH) + .wait('@projectFixturePublic') + .then((res) => { + console.log({ res }); + }); + cy.contains('button', 'Private').click(); + cy.wait('@updateProjectFixture').then((res) => { + assert.exists(res.request.body.public); + assert.isFalse(res.request.body.public); + }); }); }); diff --git a/compose/neurosynth-frontend/cypress/fixtures/projects/projectPut.json b/compose/neurosynth-frontend/cypress/fixtures/projects/projectPut.json new file mode 100644 index 000000000..79aea95e4 --- /dev/null +++ b/compose/neurosynth-frontend/cypress/fixtures/projects/projectPut.json @@ -0,0 +1,711 @@ +{ + "name":"Emotional vs Physical Pain in the anterior cortex meta-analysis project abc", + "description":"adding a description so that the last updated date will be changed lorem ipsum aeourigbaeo ugbaeiguba gaieubg aeilgu baegiluaebg ailueb gaeliurgbaeliug baeilg ubae ilubgaeilu bae", + "public":false, + "provenance":{ + "curationMetadata":{ + "columns":[ + { + "id":"88284ae3-e6bc-487b-93d3-8e54be448297", + "name":"not included", + "stubStudies":[ + + ] + }, + { + "id":"981a1475-93ea-4dbd-9468-3596a180d596", + "name":"included", + "stubStudies":[ + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/18502045", + "articleYear":"", + "authors":"Ushida T, Ikemoto T, Tanaka S, Shinozaki J, Taniguchi S, Murata Y, McLaughlin M, Arai YC, Tamura Y", + "doi":"10.1016/j.neulet.2008.04.085", + "exclusionTag":null, + "id":"4c629ce1-79ba-4c60-9722-201a5ae88704", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"Neuroscience letters", + "keywords":"", + "neurostoreId":"3LqMuQo92vDn", + "pmid":"18502045", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Virtual needle pain stimuli activates cortical representation of emotions in normal volunteers." + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/20510372", + "articleYear":"", + "authors":"Budell L, Jackson P, Rainville P", + "doi":"10.1016/j.neuroimage.2010.05.037", + "exclusionTag":null, + "id":"2edf895c-8a92-42f5-972d-e5e02352fa14", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"NeuroImage", + "keywords":"", + "neurostoreId":"4sMVHtqQYEgR", + "pmid":"20510372", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Brain responses to facial expressions of pain: emotional or motor mirroring?" + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/21514332", + "articleYear":"", + "authors":"Takahashi K, Taguchi T, Tanaka S, Sadato N, Qiu Y, Kakigi R, Mizumura K", + "doi":"10.1016/j.neures.2011.04.001", + "exclusionTag":null, + "id":"901ab956-6300-4012-a301-7eed7f747767", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"Neuroscience research", + "keywords":"", + "neurostoreId":"7ztw3nshcbSQ", + "pmid":"21514332", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Painful muscle stimulation preferentially activates emotion-related brain regions compared to painful skin stimulation." + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/21861676", + "articleYear":"", + "authors":"Lapate RC, Lee H, Salomons TV, van Reekum CM, Greischar LL, Davidson RJ", + "doi":"10.1162/jocn_a_00125", + "exclusionTag":null, + "id":"fe309201-6da2-4e8b-9a2f-c7e0f5b112a3", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"Journal of cognitive neuroscience", + "keywords":"", + "neurostoreId":"39XNYSNrAtma", + "pmid":"21861676", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Amygdalar function reflects common individual differences in emotion and pain regulation success." + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/21880911", + "articleYear":"", + "authors":"Hubbard CS, Labus JS, Bueller J, Stains J, Suyenobu B, Dukes GE, Kelleher DL, Tillisch K, Naliboff BD, Mayer EA", + "doi":"10.1523/JNEUROSCI.1860-11.2011", + "exclusionTag":null, + "id":"2ebe0596-6f26-48e9-aea9-223b67cca17b", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"The Journal of neuroscience : the official journal of the Society for Neuroscience", + "keywords":"", + "neurostoreId":"55eCbb58HZ9k", + "pmid":"21880911", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Corticotropin-releasing factor receptor 1 antagonist alters regional activation and effective connectivity in an emotional-arousal circuit during expectation of abdominal pain." + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/22073183", + "articleYear":"", + "authors":"Shimo K, Ueno T, Younger J, Nishihara M, Inoue S, Ikemoto T, Taniguchi S, Ushida T", + "doi":"10.1371/journal.pone.0026681", + "exclusionTag":null, + "id":"49d85af8-eabc-4cbd-872d-1d960f657396", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"PloS one", + "keywords":"", + "neurostoreId":"53Wz2LfFi9yJ", + "pmid":"22073183", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Visualization of painful experiences believed to trigger the activation of affective and emotional brain regions in subjects with low back pain." + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/22154962", + "articleYear":"", + "authors":"Bruneau EG, Pluta A, Saxe R", + "doi":"10.1016/j.neuropsychologia.2011.11.008", + "exclusionTag":null, + "id":"7ec96f39-c5a7-4f3e-9b60-c54e7894d973", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"Neuropsychologia", + "keywords":"", + "neurostoreId":"74WZB3uFs4dF", + "pmid":"22154962", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Distinct roles of the 'shared pain' and 'theory of mind' networks in processing others' emotional suffering." + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/22446299", + "articleYear":"", + "authors":"Buhle JT, Kober H, Ochsner KN, Mende-Siedlecki P, Weber J, Hughes BL, Kross E, Atlas LY, McRae K, Wager TD", + "doi":"10.1093/scan/nss038", + "exclusionTag":null, + "id":"3cf72cf1-2068-483d-bce4-354900d22af9", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"Social cognitive and affective neuroscience", + "keywords":"", + "neurostoreId":"4AWg42ESd7Am", + "pmid":"22446299", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Common representation of pain and negative emotion in the midbrain periaqueductal gray." + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/22732556", + "articleYear":"", + "authors":"Vachon-Presseau E, Roy M, Martel MO, Albouy G, Chen J, Budell L, Sullivan MJ, Jackson PL, Rainville P", + "doi":"10.1016/j.neuroimage.2012.06.030", + "exclusionTag":null, + "id":"dcabe3f1-18c7-42fa-a189-92ddd7328cbc", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"NeuroImage", + "keywords":"", + "neurostoreId":"3rdCEELEZ6JB", + "pmid":"22732556", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Neural processing of sensory and emotional-communicative information associated with the perception of vicarious pain." + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/23063451", + "articleYear":"", + "authors":"van der Heiden L, Scherpiet S, Konicar L, Birbaumer N, Veit R", + "doi":"10.1016/j.neuroimage.2012.10.003", + "exclusionTag":null, + "id":"0ac51b78-6c1c-4604-930b-f80efcdc7a35", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"NeuroImage", + "keywords":"", + "neurostoreId":"y5tfdVAraBwq", + "pmid":"23063451", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Inter-individual differences in successful perspective taking during pain perception mediates emotional responsiveness in self and others: an fMRI study." + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/23566889", + "articleYear":"", + "authors":"Cheon BK, Im DM, Harada T, Kim JS, Mathur VA, Scimeca JM, Parrish TB, Park H, Chiao JY", + "doi":"10.1016/j.neuropsychologia.2013.03.018", + "exclusionTag":null, + "id":"23bba6f2-bd8f-4b72-8867-51ba1867e5c1", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"Neuropsychologia", + "keywords":"", + "neurostoreId":"6w7Tz9fwRtLg", + "pmid":"23566889", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Cultural modulation of the neural correlates of emotional pain perception: the role of other-focusedness." + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/23752177", + "articleYear":"", + "authors":"Kamping S, Bomba IC, Kanske P, Diesch E, Flor H", + "doi":"10.1016/j.pain.2013.06.003", + "exclusionTag":null, + "id":"e1874700-b7d8-4ce8-a159-1ada9d3deba3", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"Pain", + "keywords":"", + "neurostoreId":"7kUjVE7yPSaq", + "pmid":"23752177", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Deficient modulation of pain by a positive emotional context in fibromyalgia patients." + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/23983029", + "articleYear":"", + "authors":"Hashmi JA, Baliki MN, Huang L, Baria AT, Torbey S, Hermann KM, Schnitzer TJ, Apkarian AV", + "doi":"10.1093/brain/awt211", + "exclusionTag":null, + "id":"235f4057-1994-478a-8ac9-c7adb4a8ed63", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"Brain : a journal of neurology", + "keywords":"", + "neurostoreId":"54qajmhxQBs6", + "pmid":"23983029", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Shape shifting pain: chronification of back pain shifts brain representation from nociceptive to emotional circuits." + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/25208742", + "articleYear":"", + "authors":"Salomons TV, Nusslock R, Detloff A, Johnstone T, Davidson RJ", + "doi":"10.1162/jocn_a_00702", + "exclusionTag":null, + "id":"24c3883c-f435-4d5d-a5e4-df2f53a012ca", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"Journal of cognitive neuroscience", + "keywords":"", + "neurostoreId":"5Bi5Sh63u6EH", + "pmid":"25208742", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Neural emotion regulation circuitry underlying anxiolytic effects of perceived control over pain." + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/25396729", + "articleYear":"", + "authors":"Laeger I, Dobel C, Radenz B, Kugel H, Keuper K, Eden A, Arolt V, Zwitserlood P, Dannlowski U, Zwanzger P", + "doi":"10.1371/journal.pone.0109949", + "exclusionTag":null, + "id":"dd2662ea-83a4-4db0-b651-957d64b62203", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"PloS one", + "keywords":"", + "neurostoreId":"7Zxy4YoV24xZ", + "pmid":"25396729", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Of 'disgrace' and 'pain' - corticolimbic interaction patterns for disorder-relevant and emotional words in social phobia." + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/25605968", + "articleYear":"", + "authors":"Wang C, Wu B, Liu Y, Wu X, Han S", + "doi":"10.1093/scan/nsv005", + "exclusionTag":null, + "id":"8b99e5d8-7fa2-40bf-a46c-ea73cd7615d0", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"Social cognitive and affective neuroscience", + "keywords":"", + "neurostoreId":"GLz2mFBHedt5", + "pmid":"25605968", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Challenging emotional prejudice by changing self-concept: priming independent self-construal reduces racial in-group bias in neural responses to other's pain." + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/25671563", + "articleYear":"", + "authors":"Budell L, Kunz M, Jackson PL, Rainville P", + "doi":"10.1371/journal.pone.0107526", + "exclusionTag":null, + "id":"49fb402b-c1cf-4b89-82f0-d8a04f050f2a", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"PloS one", + "keywords":"", + "neurostoreId":"3dxtKE8oBCDT", + "pmid":"25671563", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Mirroring pain in the brain: emotional expression versus motor imitation." + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/29258849", + "articleYear":"", + "authors":"Qiao-Tasserit E, Corradi-Dell'Acqua C, Vuilleumier P", + "doi":"10.1016/j.neuropsychologia.2017.12.027", + "exclusionTag":null, + "id":"2398271b-8fe7-49b0-8b0d-4b8cf788db8a", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"Neuropsychologia", + "keywords":"", + "neurostoreId":"GD4L8f8poNaE", + "pmid":"29258849", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"The good, the bad, and the suffering. Transient emotional episodes modulate the neural circuits of pain and empathy." + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/29662445", + "articleYear":"", + "authors":"Zhang Y, Mao Z, Pan L, Ling Z, Liu X, Zhang J, Yu X", + "doi":"10.3389/fnhum.2018.00107", + "exclusionTag":null, + "id":"58dc1652-fde6-4f24-a59c-30c862ec3973", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"Frontiers in human neuroscience", + "keywords":"", + "neurostoreId":"6wfjKuLfhbEk", + "pmid":"29662445", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Dysregulation of Pain- and Emotion-Related Networks in Trigeminal Neuralgia." + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/24062659", + "articleYear":"", + "authors":"", + "doi":"", + "exclusionTag":null, + "id":"21bf8fe6-c288-41c3-a9ba-2911704f67c8", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"", + "keywords":"", + "neurostoreId":"7GePz7Fxq6M5", + "pmid":"24062659", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Emotional modulation of experimental pain: a source imaging study of laser evoked potentials" + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/24424389", + "articleYear":"", + "authors":"", + "doi":"", + "exclusionTag":null, + "id":"4a77d8fc-74ad-42df-907c-2bc494140385", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"", + "keywords":"", + "neurostoreId":"8K2VUUynUP8M", + "pmid":"24424389", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"Emotional contagion for pain is intact in autism spectrum disorders" + }, + { + "abstractText":"", + "articleLink":"https://pubmed.ncbi.nlm.nih.gov/28259800", + "articleYear":"", + "authors":"", + "doi":"", + "exclusionTag":null, + "id":"a47950dd-3794-420e-b74d-62879155c2bb", + "identificationSource":{ + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + "journal":"", + "keywords":"", + "neurostoreId":"7MbiShMxeZNF", + "pmid":"28259800", + "searchTerm":"?genericSearchStr=emotional+pain&dataType=coordinate&source=all&sortBy=relevance&descOrder=true", + "tags":[ + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "title":"The interaction of emotion and pain in the insula and secondary somatosensory cortex" + } + ] + } + ], + "exclusionTags":[ + { + "id":"neurosynth_exclude_exclusion", + "isAssignable":true, + "isExclusionTag":true, + "label":"Exclude" + }, + { + "id":"neurosynth_duplicate_exclusion", + "isAssignable":true, + "isExclusionTag":true, + "label":"Duplicate" + } + ], + "identificationSources":[ + { + "id":"neurosynth_neurostore_id_source", + "label":"Neurostore" + }, + { + "id":"neurosynth_pubmed_id_source", + "label":"PubMed" + }, + { + "id":"neurosynth_scopus_id_source", + "label":"Scopus" + }, + { + "id":"neurosynth_web_of_science_id_source", + "label":"Web of Science" + }, + { + "id":"neurosynth_psycinfo_id_source", + "label":"PsycInfo" + } + ], + "infoTags":[ + { + "id":"neurosynth_untagged_tag", + "isAssignable":false, + "isExclusionTag":false, + "label":"Untagged studies" + }, + { + "id":"neurosynth_uncategorized_tag", + "isAssignable":false, + "isExclusionTag":false, + "label":"Uncategorized Studies" + }, + { + "id":"neurosynth_needs_review_tag", + "isAssignable":false, + "isExclusionTag":false, + "label":"Needs Review" + }, + { + "id":"fca43b33-bbcf-4c12-a6cc-06118ff7d364", + "isAssignable":true, + "isExclusionTag":false, + "label":"emotional pain (datatype=coordinate)" + } + ], + "prismaConfig":{ + "eligibility":{ + "exclusionTags":[ + + ] + }, + "identification":{ + "exclusionTags":[ + + ] + }, + "isPrisma":false, + "screening":{ + "exclusionTags":[ + + ] + } + } + }, + "extractionMetadata":{ + "annotationId":"7GpCejT5D628", + "studyStatusList":[ + { + "id":"3DHHkeKrwgdo", + "status":"completed" + } + ], + "studysetId":"4uLzwmHx8N4x" + }, + "metaAnalysisMetadata":{ + "canEditMetaAnalyses":false + } + } + } \ No newline at end of file diff --git a/compose/neurosynth-frontend/src/components/TextEdit/TextEdit.tsx b/compose/neurosynth-frontend/src/components/TextEdit/TextEdit.tsx index ecff5afd8..187c0ff0c 100644 --- a/compose/neurosynth-frontend/src/components/TextEdit/TextEdit.tsx +++ b/compose/neurosynth-frontend/src/components/TextEdit/TextEdit.tsx @@ -100,7 +100,7 @@ const TextEdit: React.FC = (props) => { }} onClick={() => setEditMode(true)} > - + )} diff --git a/compose/neurosynth-frontend/src/pages/CurationPage/ProjectIsLoadingText.tsx b/compose/neurosynth-frontend/src/pages/CurationPage/ProjectIsLoadingText.tsx index 37438b814..41d6e111c 100644 --- a/compose/neurosynth-frontend/src/pages/CurationPage/ProjectIsLoadingText.tsx +++ b/compose/neurosynth-frontend/src/pages/CurationPage/ProjectIsLoadingText.tsx @@ -1,24 +1,48 @@ import { Box, Typography } from '@mui/material'; -import { useUpdateProjectIsLoading } from 'pages/Projects/ProjectPage/ProjectStore'; +import { + useProjectMetadataHasUnsavedchanges, + useUpdateProjectIsLoading, +} from 'pages/Projects/ProjectPage/ProjectStore'; const ProjectIsLoadingText: React.FC<{ isLoading?: boolean }> = (props) => { const updateProjectIsLoading = useUpdateProjectIsLoading(); + const projectMetadataHasUnsavedchanges = useProjectMetadataHasUnsavedchanges(); const isLoading = updateProjectIsLoading || props.isLoading; - return ( - - - updating... - - - ); + if (isLoading) { + return ( + + + updating... + + + ); + } + + if (projectMetadataHasUnsavedchanges) { + return ( + + + unsaved changes + + + ); + } + + return <>; }; export default ProjectIsLoadingText; diff --git a/compose/neurosynth-frontend/src/pages/MetaAnalyses/MetaAnalysisPage/MetaAnalysisPage.tsx b/compose/neurosynth-frontend/src/pages/MetaAnalyses/MetaAnalysisPage/MetaAnalysisPage.tsx index 100a273c5..2aa2ec2bc 100644 --- a/compose/neurosynth-frontend/src/pages/MetaAnalyses/MetaAnalysisPage/MetaAnalysisPage.tsx +++ b/compose/neurosynth-frontend/src/pages/MetaAnalyses/MetaAnalysisPage/MetaAnalysisPage.tsx @@ -22,6 +22,7 @@ import { EAnalysisType } from 'hooks/metaAnalyses/useCreateAlgorithmSpecificatio import useGetMetaAnalysisResultById from 'hooks/metaAnalyses/useGetMetaAnalysisResultById'; import useGetSpecificationById from 'hooks/metaAnalyses/useGetSpecificationById'; import useUpdateMetaAnalysis from 'hooks/metaAnalyses/useUpdateMetaAnalysis'; +import useUserCanEdit from 'hooks/useUserCanEdit'; import { Annotation, ResultReturn, @@ -40,7 +41,6 @@ import { useMemo, useState } from 'react'; import { useParams } from 'react-router-dom'; import { NeurostoreAnnotation } from 'utils/api'; import MetaAnalysisPageStyles from './MetaAnalysisPage.styles'; -import useUserCanEdit from 'hooks/useUserCanEdit'; import { getResultStatus } from 'components/ProjectComponents/ViewMetaAnalyses/ViewMetaAnalysis'; const metaAnalysisSpecification: IMetaAnalysisParamsSpecification = metaAnalysisSpec; diff --git a/compose/neurosynth-frontend/src/pages/Projects/ProjectPage/ProjectPage.tsx b/compose/neurosynth-frontend/src/pages/Projects/ProjectPage/ProjectPage.tsx index 5011a56c8..03e21581e 100644 --- a/compose/neurosynth-frontend/src/pages/Projects/ProjectPage/ProjectPage.tsx +++ b/compose/neurosynth-frontend/src/pages/Projects/ProjectPage/ProjectPage.tsx @@ -1,4 +1,6 @@ -import { Box, Tab, Tabs, Typography } from '@mui/material'; +import LockIcon from '@mui/icons-material/Lock'; +import PublicIcon from '@mui/icons-material/Public'; +import { Box, Chip, Tab, Tabs, ToggleButton, ToggleButtonGroup, Typography } from '@mui/material'; import NeurosynthBreadcrumbs from 'components/NeurosynthBreadcrumbs/NeurosynthBreadcrumbs'; import StateHandlerComponent from 'components/StateHandlerComponent/StateHandlerComponent'; import TextEdit from 'components/TextEdit/TextEdit'; @@ -7,12 +9,15 @@ import ProjectIsLoadingText from 'pages/CurationPage/ProjectIsLoadingText'; import { useGetProjectIsLoading, useInitProjectStoreIfRequired, + useProjectCreatedAt, useProjectDescription, + useProjectIsPublic, useProjectMetaAnalysisCanEdit, useProjectName, useProjectUser, useProjectUsername, useUpdateProjectDescription, + useUpdateProjectIsPublic, useUpdateProjectName, } from 'pages/Projects/ProjectPage/ProjectStore'; import { useMemo } from 'react'; @@ -36,13 +41,15 @@ const ProjectPage: React.FC = (props) => { const updateProjectName = useUpdateProjectName(); const updateProjectDescription = useUpdateProjectDescription(); + const updateProjectIsPublic = useUpdateProjectIsPublic(); const metaAnalysesTabEnabled = useProjectMetaAnalysisCanEdit(); const getProjectIsLoading = useGetProjectIsLoading(); const projectName = useProjectName(); + const createdAt = useProjectCreatedAt(); const projectUser = useProjectUser(); const projectUserName = useProjectUsername(); const projectDescription = useProjectDescription(); - + const isPublic = useProjectIsPublic(); const userCanEdit = useUserCanEdit(projectUser || undefined); const tab = useMemo( @@ -72,43 +79,93 @@ const ProjectPage: React.FC = (props) => { - updateProjectName(updatedName)} - sx={{ input: { fontSize: '1.5rem' } }} - textToEdit={projectName || ''} - editIconIsVisible={userCanEdit} - > - + { + // do not update if newVal is the same as the current value or if it doesnt exist + if (newVal === null || newVal === isPublic) return; + updateProjectIsPublic(newVal === 'PUBLIC'); }} - variant="h5" + color="primary" + value={isPublic ? 'PUBLIC' : 'PRIVATE'} + size="small" > - {projectName || 'No name'} - - - - updateProjectDescription(updatedDescription) - } - sx={{ input: { fontSize: '1.25rem' } }} - textToEdit={projectDescription || ''} - editIconIsVisible={userCanEdit} - multiline - > - + Public + + + Private + + + + + updateProjectName(updatedName)} + sx={{ input: { fontSize: '1.5rem' } }} + textToEdit={projectName || ''} + editIconIsVisible={userCanEdit} + > + + {projectName || 'No name'} + + + + updateProjectDescription(updatedDescription) + } + sx={{ input: { fontSize: '1.25rem' } }} + textToEdit={projectDescription || ''} + editIconIsVisible={userCanEdit} + multiline + > + + {projectDescription || 'No description'} + + + - {projectDescription || 'No description'} - - - - Owner: {projectUserName || 'No owner'} - + + {projectUserName && ( + + )} + {createdAt && ( + + )} + + + diff --git a/compose/neurosynth-frontend/src/pages/Projects/ProjectPage/ProjectStore.ts b/compose/neurosynth-frontend/src/pages/Projects/ProjectPage/ProjectStore.ts index bcdbc0e5c..560447f3f 100644 --- a/compose/neurosynth-frontend/src/pages/Projects/ProjectPage/ProjectStore.ts +++ b/compose/neurosynth-frontend/src/pages/Projects/ProjectPage/ProjectStore.ts @@ -40,7 +40,6 @@ import { import { EExtractionStatus } from 'pages/ExtractionPage/ExtractionPage'; export type ProjectStoreMetadata = { - shouldUpdate: boolean; // this flag is for the debouncer enqueueSnackbar: | undefined | ((message: SnackbarMessage, options?: OptionsObject | undefined) => SnackbarKey); @@ -49,6 +48,7 @@ export type ProjectStoreMetadata = { prevUpdatedProjectId: undefined | string; getProjectIsLoading: boolean; updateProjectIsLoading: boolean; + hasUnsavedChanges: boolean; isError: boolean; error: string | undefined; updateProject: @@ -64,6 +64,7 @@ export type ProjectStoreMetadata = { export type ProjectStoreActions = { updateProjectInDBDebounced: () => void; updateProjectName: (name: string) => void; + updateProjectIsPublic: (isPublic: boolean) => void; updateProjectDescription: (description: string) => void; initProjectStore: (project: INeurosynthProjectReturn | undefined) => void; updateProjectMetaAnalyses: (meta_analyses: string[]) => void; @@ -143,7 +144,6 @@ const useProjectStore = create()((set, get) => { }, metadata: { - shouldUpdate: false, enqueueSnackbar: undefined, updateProject: undefined, logout: undefined, @@ -153,6 +153,7 @@ const useProjectStore = create()((set, get) => { updateProjectIsLoading: false, isError: false, error: undefined, + hasUnsavedChanges: false, }, // just for testing purposes @@ -253,6 +254,7 @@ const useProjectStore = create()((set, get) => { const update: INeurosynthProject = { name: oldDebouncedStoreData.name, description: oldDebouncedStoreData.description, + public: oldDebouncedStoreData.public, provenance: { ...oldDebouncedStoreData.provenance, }, @@ -265,6 +267,10 @@ const useProjectStore = create()((set, get) => { set((state) => ({ ...state, updated_at: res.data.updated_at, + metadata: { + ...state.metadata, + hasUnsavedChanges: false, + }, })); }, onError: (err) => { @@ -324,6 +330,7 @@ const useProjectStore = create()((set, get) => { ...state.metadata, prevUpdatedProjectId: oldDebouncedStoreData.id, debounceTimeout: newTimeout, + hasUnsavedChanges: true, }, })); }, @@ -382,7 +389,6 @@ const useProjectStore = create()((set, get) => { }, }, metadata: { - shouldUpdate: false, enqueueSnackbar: undefined, logout: undefined, updateProject: undefined, @@ -392,6 +398,7 @@ const useProjectStore = create()((set, get) => { updateProjectIsLoading: false, isError: false, error: undefined, + hasUnsavedChanges: false, }, })); }, @@ -405,10 +412,6 @@ const useProjectStore = create()((set, get) => { ...initCurationHelper(cols, isPrisma), }, }, - metadata: { - ...state.metadata, - shouldUpdate: true, - }, })); get().updateProjectInDBDebounced(); @@ -421,6 +424,14 @@ const useProjectStore = create()((set, get) => { get().updateProjectInDBDebounced(); }, + updateProjectIsPublic: (isPublic: boolean) => { + set((state) => ({ + ...state, + public: isPublic, + })); + + get().updateProjectInDBDebounced(); + }, updateProjectDescription: (description: string) => { set((state) => ({ ...state, @@ -739,7 +750,14 @@ const useProjectStore = create()((set, get) => { }; }); +// project metadata retrieval hooks +export const useProjectMetadataHasUnsavedchanges = () => + useProjectStore((state) => state.metadata.hasUnsavedChanges); + // higher level project retrieval hooks +export const useProjectIsPublic = () => useProjectStore((state) => state.public); +export const useProjectCreatedAt = () => + useProjectStore((state) => new Date(state.created_at || '')); export const useProjectName = () => useProjectStore((state) => state.name); export const useProjectDescription = () => useProjectStore((state) => state.description); export const useProjectProvenance = () => useProjectStore((state) => state.provenance); @@ -776,6 +794,8 @@ export const useProjectCurationExclusionTags = () => useProjectStore((state) => state.provenance.curationMetadata.exclusionTags); // curation updater hooks +export const useUpdateProjectIsPublic = () => + useProjectStore((state) => state.updateProjectIsPublic); export const useUpdateProjectName = () => useProjectStore((state) => state.updateProjectName); export const useUpdateProjectDescription = () => useProjectStore((state) => state.updateProjectDescription); @@ -835,7 +855,6 @@ export const useInitProjectStoreIfRequired = () => { updateProject: mutate, logout: logout, enqueueSnackbar: enqueueSnackbar, - shouldUpdate: true, getProjectIsLoading: getProjectIsLoading, updateProjectIsLoading: useUpdateProjectIsLoading, isError: isError,