4898794edd81be5285ea6e544acbedeaeb31bf78 max Tue Nov 23 08:10:57 2021 -0800 Fixing pointers to README file for license in all source code files. refs #27614 diff --git src/hg/hgc/wikiTrack.c src/hg/hgc/wikiTrack.c index 1ac4bab..0c78eca 100644 --- src/hg/hgc/wikiTrack.c +++ src/hg/hgc/wikiTrack.c @@ -1,588 +1,588 @@ /* Handle details pages for wiggle tracks. */ /* Copyright (C) 2013 The Regents of the University of California - * See README in this or parent directory for licensing information. */ + * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */ #include "common.h" #include "cart.h" #include "hgc.h" #include "hCommon.h" #include "hgColors.h" #include "hgConfig.h" #include "obscure.h" #include "binRange.h" #include "web.h" #include "net.h" #include "grp.h" #include "hui.h" #include "htmlPage.h" #include "wikiLink.h" #include "wikiTrack.h" #define ITEM_SCORE_DEFAULT "1000" #define ADD_ITEM_COMMENT_DEFAULT "add comments" static void colorMenuOutput() /* the item color pull-down menu in the create item form */ { hPrintf("<INPUT NAME=\"colorPullDown\" VALUE=\"\" SIZE=1 STYLE=\"display:none;\" >\n"); hPrintf("<SELECT NAME=\"%s\" id='%s' style=\"width:8em; background-color:#000000;\">\n" , NEW_ITEM_COLOR, NEW_ITEM_COLOR); jsOnEventById("change", NEW_ITEM_COLOR, "updateColorSelectBox();"); hPrintf("<OPTION SELECTED VALUE = \"#000000\" style=\"background-color:#000000;\" >black</OPTION>\n"); hPrintf("<OPTION value = \"#0000ff\" style=\"background-color:#0000ff;\" >blue</OPTION>\n"); hPrintf("<OPTION VALUE = \"#9600c8\" style=\"background-color:#9600c8;\" >purple</OPTION>\n"); hPrintf("<OPTION VALUE = \"#ff0000\" style=\"background-color:#ff0000;\" >red</OPTION>\n"); hPrintf("<OPTION VALUE = \"#e67800\" style=\"background-color:#e67800;\" >orange</OPTION>\n"); hPrintf("<OPTION VALUE = \"#dcdc00\" style=\"background-color:#dcdc00;\" >yellow</OPTION>\n"); hPrintf("<OPTION VALUE = \"#00b400\" style=\"background-color:#00b400;\" >green</OPTION>\n"); hPrintf("<OPTION VALUE = \"#8c8c8c\" style=\"background-color:#8c8c8c;\" >gray</OPTION>\n"); hPrintf("</SELECT>\n"); } static char *encodedHgcReturnUrl(int id, char *table) /* Return a CGI-encoded hgc URL with hgsid and given id. Free when done. */ { char retBuf[1024]; int o = cartUsualInt(cart, "o", winStart); safef(retBuf, sizeof(retBuf), "http://%s/cgi-bin/hgc?%s&g=%s&c=%s&o=%d&l=%d&r=%d&db=%s&i=%d", cgiServerNamePort(), cartSidUrlString(cart), table, seqName, o, winStart, winEnd, database, id); return cgiEncode(retBuf); } static char *wikiTrackUserLoginUrl(int id, char *table) /* Return the URL for the wiki user login page. */ { char *retEnc = encodedHgcReturnUrl(id, table); char buf[2048]; if (! wikiLinkEnabled()) errAbort("wikiLinkUserLoginUrl called when wiki is not enabled (specified " "in hg.conf)."); safef(buf, sizeof(buf), "%s/index.php?title=Special:UserloginUCSC&returnto=%s", cfgOptionDefault(CFG_WIKI_URL, NULL), retEnc); freez(&retEnc); return(cloneString(buf)); } void offerLogin(int id, char *loginType, char *table) /* display login prompts to the wiki when user isn't already logged in */ { char *wikiHost = wikiLinkHost(); char *loginUrl = wikiTrackUserLoginUrl(id, table); printf("<P>Please login to %s the annotation track.</P>\n", loginType); printf("<P>The login page is handled by our " "<A HREF=\"http://%s/\" TARGET=_BLANK>wiki system</A>:\n", wikiHost); printf("<A HREF=\"%s\"><B>click here to login.</B></A><BR>\n", loginUrl); printf("The wiki also serves as a forum for users " "to share knowledge and ideas.\n</P>\n"); freeMem(loginUrl); freeMem(wikiHost); webIncludeHelpFile("wikiTrackAddCommentHelp", TRUE); webIncludeHelpFile("wikiTrack", TRUE); } static void startForm(char *name, char *actionType) { hPrintf("<FORM ID=\"%s\" NAME=\"%s\" ACTION=\"%s\">\n\n", name, name, hgcName()); cartSaveSession(cart); cgiMakeHiddenVar("g", actionType); cgiContinueHiddenVar("c"); cgiContinueHiddenVar("o"); hPrintf("\n"); cgiContinueHiddenVar("l"); cgiContinueHiddenVar("r"); hPrintf("\n"); } static struct bed *multipleItems(struct wikiTrack *item) { struct sqlResult *sr; char **row; struct sqlConnection *wikiConn = wikiConnect(); char query[1024]; struct bed *bedList = NULL; sqlSafef(query, ArraySize(query), "SELECT chrom,chromStart,chromEnd,id FROM %s " "WHERE descriptionKey='%s' ORDER BY chrom,chromStart;", WIKI_TRACK_TABLE, item->descriptionKey); sr = sqlGetResult(wikiConn, query); while ( (row = sqlNextRow(sr)) != NULL) { int elId = sqlUnsigned(row[3]); if (elId == item->id) continue; struct bed *bed; AllocVar(bed); bed->chrom = cloneString(row[0]); bed->chromStart = sqlUnsigned(row[1]); bed->chromEnd = sqlUnsigned(row[2]); bed->score = elId; slAddHead(&bedList,bed); } sqlFreeResult(&sr); slSort(&bedList, bedCmpExtendedChr); wikiDisconnect(&wikiConn); return bedList; } static void displayItem(struct wikiTrack *item, char *userName) /* given an already fetched item, get the item description from * the wiki. Put up edit form(s) if userName is not NULL */ { boolean geneAnnotation = FALSE; char *url = cfgOptionDefault(CFG_WIKI_URL, NULL); if (isNotEmpty(item->geneSymbol) && differentWord(item->geneSymbol,"0")) { hPrintf("<B>This is a UCSC gene annotation</B><BR>\n"); geneAnnotation = TRUE; } else hPrintf("<B>This is a genome location annotation, not a gene annotation.</B>\n"); printPosOnChrom(item->chrom, item->chromStart, item->chromEnd, item->strand, FALSE, item->name); if (geneAnnotation) { struct bed *itemList = multipleItems(item); if (slCount(itemList) > 0) { hPrintf(" This gene symbol <B>'%s'</B> is also found in the following " "locations:<BR>\n", item->name); struct bed *el; for (el = itemList; el; el = el->next) { printf(" <B>%s:</B> " "<A HREF=\"%s&db=%s&position=%s%%3A%d-%d\">", item->name, hgTracksPathAndSettings(), database, el->chrom, el->chromStart+1, el->chromEnd); printf("%s:%d-%d</A><BR>\n", el->chrom, el->chromStart+1, el->chromEnd); } } } hPrintf("<B>Created </B>%s<B> by: </B>", item->creationDate); hPrintf("<A HREF=\"%s/index.php/User:%s\" TARGET=_blank>%s</A><BR>\n", url, item->owner, item->owner); hPrintf("<B>Most recent quick update: </B>%s<BR>\n", item->lastModifiedDate); boolean editor = isWikiEditor(userName); if ((NULL != userName) && (editor || (sameWord(userName, item->owner) && !geneAnnotation))) { hPrintf("<em>(comments for deleted items remain in the wiki, with a " "note<BR> that the item has been deleted.)</em><BR>\n"); startForm("deleteForm", G_DELETE_WIKI_ITEM); char idString[128]; safef(idString, ArraySize(idString), "%d", item->id); cgiMakeHiddenVar("i", idString); hPrintf("\n"); webPrintLinkTableStart(); webPrintLinkCellStart(); if (editor && (differentWord(userName, item->owner) || geneAnnotation)) hPrintf("Editor '%s' has deletion rights ", userName); else hPrintf("Owner '%s' has deletion rights ", item->owner); webPrintLinkCellEnd(); webPrintLinkCellStart(); cgiMakeButton("submit", "DELETE"); webPrintLinkCellEnd(); webPrintLinkCellStart(); hPrintf(" (no questions asked)"); webPrintLinkCellEnd(); webPrintLinkTableEnd(); hPrintf("\n</FORM>\n"); } hPrintf("<B>View the wiki article " "<A HREF=\"%s/index.php/%s\" TARGET=_blank>%s:</A> to see " "existing comments.</B><BR>\n", url, item->descriptionKey, item->descriptionKey); if (NULL != userName) hPrintf("<B>Mark this wiki article as <em>" "<A HREF=\"%s/index.php/%s?action=watch\" TARGET=_blank>watched</A>" "</em> to receive email notices of any comment additions.</B><BR>\n", url, item->descriptionKey); hPrintf("<HR>\n"); if (NULL == userName) { if (! wikiTrackReadOnly() ) /* read-only option 2012-06-25 */ offerLogin(item->id, "add comments to items on", WIKI_TRACK_TABLE); } else if (emailVerified(TRUE)) /* do print message when not verified */ { startForm("addComments", G_ADD_WIKI_COMMENTS); char idString[128]; safef(idString, ArraySize(idString), "%d", item->id); cgiMakeHiddenVar("i", idString); hPrintf("\n"); webPrintLinkTableStart(); /* first row is a title line */ char label[256]; safef(label, ArraySize(label), "'%s' quick add comments to item '%s'\n", userName, item->name); webPrintWideLabelCell(label, 2); webPrintLinkTableNewRow(); /* second row is initial comment/description text entry */ webPrintWideCellStart(2, HG_COL_TABLE); cgiMakeTextArea(NEW_ITEM_COMMENT, ADD_ITEM_COMMENT_DEFAULT, 3, 70); webPrintLinkCellEnd(); webPrintLinkTableNewRow(); /*webPrintLinkCellStart(); more careful explicit alignment */ hPrintf("<TD BGCOLOR=\"#%s\" ALIGN=\"CENTER\" VALIGN=\"TOP\">", HG_COL_TABLE); cgiMakeButton("submit", "add comments"); hPrintf("\n</FORM>\n"); webPrintLinkCellEnd(); /*webPrintLinkCellStart(); doesn't valign center properly */ hPrintf("<TD BGCOLOR=\"#%s\" ALIGN=\"CENTER\" VALIGN=\"TOP\">", HG_COL_TABLE); hPrintf("\n<FORM ID=\"cancel\" NAME=\"cancel\" ACTION=\"%s\">", hgTracksName()); cgiMakeButton("cancel", "return to tracks display"); hPrintf("\n</FORM>\n"); webPrintLinkCellEnd(); webPrintLinkTableEnd(); hPrintf("For more extensive edits, please edit the "); hPrintf("wiki article <A HREF=\"%s/index.php/%s\" TARGET=_blank>%s</A> " "in the wiki editing system.<BR>", url, item->descriptionKey, item->descriptionKey); webIncludeHelpFile("wikiTrackAddCommentHelp", TRUE); webIncludeHelpFile("wikiTrack", TRUE); } } /* displayItem() */ void outputJavaScript() /* java script functions used in the create item form */ { hPrintf("<SCRIPT TYPE=\"text/javascript\">\n"); hPrintf("function updateColorSelectBox() {\n" " var form = document.getElementById(\"createItem\");\n" " document.createItem.colorPullDown.style.display='inline';\n" " document.createItem.colorPullDown.select();\n" " document.createItem.colorPullDown.style.display='none';\n" " form.%s.style.background = form.%s[form.%s.selectedIndex].value;\n" " form.%s.style.color = form.%s[form.%s.selectedIndex].value;\n" "}\n", NEW_ITEM_COLOR, NEW_ITEM_COLOR, NEW_ITEM_COLOR, NEW_ITEM_COLOR, NEW_ITEM_COLOR, NEW_ITEM_COLOR); hPrintf("</SCRIPT>\n"); } void doWikiTrack(char *wikiItemId, char *chrom, int winStart, int winEnd) /* handle item clicks on wikiTrack - may create new items */ { char *userName = NULL; if (wikiTrackEnabled(database, &userName) && sameWord("0", wikiItemId)) { cartWebStart(cart, database, "%s", "User Annotation Track: Create new item"); if (NULL == userName) { if (! wikiTrackReadOnly() ) /* read-only option 2012-06-25 */ { offerLogin(0, "add new items to", WIKI_TRACK_TABLE); //cartHtmlEnd(); } return; } if (emailVerified(TRUE)) /* do print message when not verified */ { outputJavaScript(); startForm("createItem", G_CREATE_WIKI_ITEM); webPrintLinkTableStart(); /* first row is a title line */ char label[256]; safef(label, ArraySize(label), "Create new item, owner: '%s'\n", userName); webPrintWideLabelCell(label, 2); webPrintLinkTableNewRow(); /* third row is position entry box */ webPrintWideCellStart(2, HG_COL_TABLE); puts("<B>position: </B>"); savePosInTextBox(seqName, winStart+1, winEnd); hPrintf(" (size: "); printLongWithCommas(stdout, (long long)(winEnd - winStart)); hPrintf(")"); webPrintLinkCellEnd(); webPrintLinkTableNewRow(); /* fourth row is strand selection radio box */ webPrintWideCellStart(2, HG_COL_TABLE); char *strand = cartUsualString(cart, NEW_ITEM_STRAND, "plus"); boolean plusStrand = sameWord("plus",strand) ? TRUE : FALSE; hPrintf("<B>strand: "); cgiMakeRadioButton(NEW_ITEM_STRAND, "plus", plusStrand); hPrintf(" + "); cgiMakeRadioButton(NEW_ITEM_STRAND, "minus", ! plusStrand); hPrintf(" -</B>"); webPrintLinkCellEnd(); webPrintLinkTableNewRow(); /* fifth row is item name text entry */ webPrintWideCellStart(2, HG_COL_TABLE); hPrintf("<B>item name: </B>"); cgiMakeTextVar("i", NEW_ITEM_NAME, 18); webPrintLinkCellEnd(); #ifdef NOT webPrintLinkTableNewRow(); /* sixth row is item score text entry */ webPrintWideCellStart(2, HG_COL_TABLE); hPrintf("<B>item score: </B>"); cgiMakeTextVar(NEW_ITEM_SCORE, ITEM_SCORE_DEFAULT, 4); hPrintf(" (range: 0 to %s)", ITEM_SCORE_DEFAULT); webPrintLinkCellEnd(); #endif webPrintLinkTableNewRow(); /* seventh row is item color pull-down menu */ webPrintWideCellStart(2, HG_COL_TABLE); hPrintf("<B>item color: </B>"); colorMenuOutput(); webPrintLinkCellEnd(); webPrintLinkTableNewRow(); /* seventh row is initial comment/description text entry */ webPrintWideCellStart(2, HG_COL_TABLE); hPrintf("<B>initial comments/description:</B><BR>"); cgiMakeTextArea(NEW_ITEM_COMMENT, NEW_ITEM_COMMENT_DEFAULT, 5, 70); webPrintLinkCellEnd(); webPrintLinkTableNewRow(); /* seventh row is the submit and cancel buttons */ /*webPrintLinkCellStart(); more careful explicit alignment */ hPrintf("<TD BGCOLOR=\"#%s\" ALIGN=\"CENTER\" VALIGN=\"TOP\">", HG_COL_TABLE); cgiMakeButton("submit", "create new item"); hPrintf("\n</FORM>\n"); webPrintLinkCellEnd(); /*webPrintLinkCellStart(); doesn't valign center properly */ hPrintf("<TD BGCOLOR=\"#%s\" ALIGN=\"CENTER\" VALIGN=\"TOP\">", HG_COL_TABLE); hPrintf("\n<FORM ID=\"cancel\" NAME=\"cancel\" ACTION=\"%s\">", hgTracksName()); cgiMakeButton("cancel", "cancel"); hPrintf("\n</FORM>\n"); webPrintLinkCellEnd(); webPrintLinkTableEnd(); hPrintf("This entry form starts the comments for this new item.<BR>\n" "Subsequent edits will be performed in the wiki editing system." "<BR>\n"); webIncludeHelpFile("wikiTrackCreateItemHelp", TRUE); webIncludeHelpFile("wikiTrack", TRUE); } } else { struct wikiTrack *item = findWikiItemId(wikiItemId); cartWebStart(cart, database, "%s (%s) %s", "User Annotation Track", item->name, wikiItemId); /* if we can get the hgc clicks to add item id to the incoming data, * then use that item Id here */ displayItem(item, userName); } } /* void doWikiTrack() */ static void updateLastModifiedDate(int id) /* set lastModifiedDate to now() */ { char query[512]; struct sqlConnection *wikiConn = wikiConnect(); sqlSafef(query, ArraySize(query), "UPDATE %s set lastModifiedDate=now() WHERE id='%d'", WIKI_TRACK_TABLE, id); sqlUpdate(wikiConn,query); wikiDisconnect(&wikiConn); } static void deleteItem(int id) /* delete the item with specified id */ { char query[512]; struct sqlConnection *wikiConn = wikiConnect(); sqlSafef(query, ArraySize(query), "DELETE FROM %s WHERE id='%d'", WIKI_TRACK_TABLE, id); sqlUpdate(wikiConn,query); wikiDisconnect(&wikiConn); } void doDeleteWikiItem(char *wikiItemId, char *chrom, int winStart, int winEnd) /* handle delete item clicks for wikiTrack */ { char *userName = NULL; struct wikiTrack *item = findWikiItemId(wikiItemId); cartWebStart(cart, database, "%s (%s)", "User Annotation Track, deleted item: ", item->name); if (NULL == wikiItemId) errAbort("delete wiki item: NULL wikiItemId"); if (! wikiTrackEnabled(database, &userName)) errAbort("delete wiki item: wiki track not enabled"); /* this may be a multiple loci gene symbol annotation */ struct bed *itemList = multipleItems(item); char comments[1024]; if (slCount(itemList) > 0) safef(comments,ArraySize(comments), "This item '''%s''' on assembly %s " "at %s:%d-%d (and %d other loci) has been deleted from the wiki track\n\n", item->name, item->db, item->chrom, item->chromStart, item->chromEnd, slCount(itemList)); else safef(comments,ArraySize(comments), "This item '''%s''' on assembly %s " "at %s:%d-%d has been deleted from the wiki track\n\n", item->name, item->db, item->chrom, item->chromStart, item->chromEnd); prefixComments(item, comments, userName, seqName, winStart, winEnd, database, NULL, "(deleted item)", NEW_ITEM_CATEGORY); deleteItem(sqlSigned(wikiItemId)); /* this may be a multiple loci gene symbol annotation */ if (slCount(itemList) > 0) { struct bed *el; for (el = itemList; el; el = el->next) deleteItem(el->score); } hPrintf("<BR>\n"); hPrintf("<FORM ID=\"delete\" NAME=\"delete\" ACTION=\"%s\">", hgTracksName()); cgiMakeButton("submit", "return to tracks display"); hPrintf("\n</FORM>\n"); hPrintf("<BR>\n"); webIncludeHelpFile("wikiTrack", TRUE); } void doAddWikiComments(char *wikiItemId, char *chrom, int winStart, int winEnd) /* handle add comment item clicks for wikiTrack */ { char *userName = NULL; struct wikiTrack *item = findWikiItemId(wikiItemId); cartWebStart(cart, database, "%s (%s)", "User Annotation Track", item->name); if (NULL == wikiItemId) errAbort("add wiki comments: NULL wikiItemId"); if (! wikiTrackEnabled(database, &userName)) errAbort("add wiki comments: wiki track not enabled"); if (NULL == userName) errAbort("add wiki comments: user not logged in ?"); addDescription(item, userName, seqName, winStart, winEnd, cart, database, NULL, NULL, NEW_ITEM_CATEGORY); updateLastModifiedDate(sqlSigned(wikiItemId)); displayItem(item, userName); } void doCreateWikiItem(char *itemName, char *chrom, int winStart, int winEnd) /* handle create item clicks for wikiTrack */ { int itemStart = 0; int itemEnd = 0; char *chrName = NULL; char *pos = NULL; char *strand = cartUsualString(cart, NEW_ITEM_STRAND, "plus"); char *class = cartUsualString(cart, NEW_ITEM_CLASS, ITEM_NOT_CLASSIFIED); boolean plusStrand = sameWord("plus",strand) ? TRUE : FALSE; char descriptionKey[256]; struct sqlConnection *wikiConn = wikiConnect(); char *userName = NULL; char *color = cartUsualString(cart, NEW_ITEM_COLOR, "#000000"); int score = 0; struct wikiTrack *newItem; if (! wikiTrackEnabled(database, &userName)) errAbort("create new wiki item: wiki track not enabled"); if (NULL == userName) errAbort("create new wiki item: user not logged in ?"); #ifdef NOT score = sqlSigned(cartUsualString(cart, NEW_ITEM_SCORE, ITEM_SCORE_DEFAULT)); #endif score = 0; pos = stripCommas(cartOptionalString(cart, "getDnaPos")); if (NULL == pos) errAbort("create new wiki item: called incorrectly, without getDnaPos"); hgParseChromRange(database, pos, &chrName, &itemStart, &itemEnd); if (NULL == chrName) webAbort("Wiki Annotation", "illegal chrom name entered: '%s'<BR>\n" "Note: chrom names are case sensitive.<BR>\n", pos); char *realChrName = hgOfficialChromName(database, chrName); if (NULL == realChrName) webAbort("Wiki Annotation", "illegal chrom name entered: '%s'<BR>\n" "Note: chrom names are case sensitive.<BR>\n", pos); if (itemStart > itemEnd) { int t = itemEnd; itemEnd = itemStart; itemStart = t; } safef(descriptionKey,ArraySize(descriptionKey), "GenomeAnnotation:%s-%d", database, 0); AllocVar(newItem); newItem->bin = binFromRange(itemStart, itemEnd); newItem->chrom = cloneString(realChrName); newItem->chromStart = itemStart; newItem->chromEnd = itemEnd; newItem->name = cloneString(itemName); newItem->score = score; safef(newItem->strand, sizeof(newItem->strand), "%s", plusStrand ? "+" : "-"); newItem->db = cloneString(database); newItem->owner = cloneString(userName); newItem->class = cloneString(class); newItem->color = cloneString(color); newItem->creationDate = cloneString("0"); newItem->lastModifiedDate = cloneString("0"); newItem->descriptionKey = cloneString(descriptionKey); newItem->id = 0; newItem->geneSymbol = cloneString("0"); wikiTrackSaveToDb(wikiConn, newItem, WIKI_TRACK_TABLE, 1024); int id = sqlLastAutoId(wikiConn); safef(descriptionKey,ArraySize(descriptionKey), "GenomeAnnotation:%s-%d", database, id); wikiTrackFree(&newItem); char newItemName[128]; char query[512]; if (sameWord(itemName,NEW_ITEM_NAME)) { safef(newItemName, ArraySize(newItemName), "%s-%d", database, id); sqlSafef(query, ArraySize(query), "UPDATE %s set creationDate=now(),lastModifiedDate=now(),descriptionKey='%s',name='%s-%d' WHERE id='%d'", WIKI_TRACK_TABLE, descriptionKey, database, id, id); } else { safef(newItemName, ArraySize(newItemName), "%s", itemName); sqlSafef(query, ArraySize(query), "UPDATE %s set creationDate=now(),lastModifiedDate=now(),descriptionKey='%s' WHERE id='%d'", WIKI_TRACK_TABLE, descriptionKey, id); } sqlUpdate(wikiConn,query); wikiDisconnect(&wikiConn); cartWebStart(cart, database, "%s %s", "User Annotation Track, created new item: ", newItemName); char wikiItemId[64]; safef(wikiItemId,ArraySize(wikiItemId),"%d", id); struct wikiTrack *item = findWikiItemId(wikiItemId); addDescription(item, userName, seqName, winStart, winEnd, cart, database, NULL, NULL, NEW_ITEM_CATEGORY); displayItem(item, userName); } /* void doCreateWikiItem() */