diff --git a/frontend/src/components/AuthenticatedAppHeader.jsx b/frontend/src/components/AuthenticatedAppHeader.jsx index 3860eb9130..a32811fac0 100644 --- a/frontend/src/components/AuthenticatedAppHeader.jsx +++ b/frontend/src/components/AuthenticatedAppHeader.jsx @@ -8,20 +8,13 @@ import AvatarAndUserProfile from "./header/AvatarAndUserProfile"; import { debounce } from "lodash"; import Menu from "./header/Menu"; import FooterVisibilityContext from "../FooterVisibilityContext"; +import Logo from "./svg/Logo"; export default function AuthenticatedAppHeader({ username, avatar, showAlert, }) { - const location = window.location; - const path = location.pathname.endsWith("/") - ? location.pathname - : location.pathname + "/"; - const homePage = path === "/react/home/" || path === "/react/"; - const [backgroundColor, setBackgroundColor] = useState( - homePage ? "transparent" : "#00a1b2", - ); const { visible } = useContext(FooterVisibilityContext); const { @@ -32,24 +25,14 @@ export default function AuthenticatedAppHeader({ getAllNotifications, } = useContext(AuthContext); - useEffect(() => { - const handleScroll = debounce(() => { - const currentScrollY = window.scrollY; - setBackgroundColor( - homePage && currentScrollY > 40 ? "#00a1b2" : "transparent", - ); - }, 200); - window.addEventListener("scroll", handleScroll); - return () => window.removeEventListener("scroll", handleScroll); - }, []); - return visible ? ( - + + {process.env.SITE_NAME} diff --git a/frontend/src/components/Avatar.jsx b/frontend/src/components/Avatar.jsx index 30442e5200..9a20d7bf07 100644 --- a/frontend/src/components/Avatar.jsx +++ b/frontend/src/components/Avatar.jsx @@ -1,22 +1,24 @@ -import React from 'react'; +import React from "react"; export default function Avatar({ avatar }) { - return ( -
- img -
- ); -} \ No newline at end of file + return ( +
+ img +
+ ); +} diff --git a/frontend/src/components/UnAuthenticatedAppHeader.jsx b/frontend/src/components/UnAuthenticatedAppHeader.jsx index 26fa6b05b0..f8bc443ce0 100644 --- a/frontend/src/components/UnAuthenticatedAppHeader.jsx +++ b/frontend/src/components/UnAuthenticatedAppHeader.jsx @@ -8,16 +8,9 @@ import MultiLanguageDropdown from "./navBar/MultiLanguageDropdown"; import { FormattedMessage } from "react-intl"; import NotificationButton from "./navBar/NotificationButton"; import FooterVisibilityContext from "../FooterVisibilityContext"; +import Logo from "./svg/Logo"; export default function AuthenticatedAppHeader({ showAlert }) { - const location = window.location; - const path = location.pathname.endsWith("/") - ? location.pathname - : location.pathname + "/"; - const homePage = path === "/react/home/" || path === "/react/"; - const [backgroundColor, setBackgroundColor] = useState( - homePage ? "transparent" : "#00a1b2", - ); const { visible } = useContext(FooterVisibilityContext); const [dropdownShows, setDropdownShows] = useState({ @@ -37,25 +30,14 @@ export default function AuthenticatedAppHeader({ showAlert }) { setDropdownBorder((prev) => ({ ...prev, [id]: "2px solid transparent" })); }; - useEffect(() => { - const handleScroll = () => { - const currentScrollY = window.scrollY; - if (homePage && currentScrollY > 40) { - setBackgroundColor("#00a1b2"); - } else if (homePage) { - setBackgroundColor("transparent"); - } - }; - window.addEventListener("scroll", handleScroll); - return () => window.removeEventListener("scroll", handleScroll); - }, []); return visible ? ( - + + {process.env.SITE_NAME} diff --git a/frontend/src/components/svg/Logo.jsx b/frontend/src/components/svg/Logo.jsx index 4c3812b5eb..f53b335da0 100644 --- a/frontend/src/components/svg/Logo.jsx +++ b/frontend/src/components/svg/Logo.jsx @@ -1,18 +1,35 @@ -import React from 'react'; +import React from "react"; -export default function Logo({style}) { - return
- - - - - - - - - - - - +export default function Logo({ style }) { + return ( +
+ + + + +
-} \ No newline at end of file + ); +} diff --git a/src/main/java/org/ecocean/security/Collaboration.java b/src/main/java/org/ecocean/security/Collaboration.java index 319137cfa9..5c959c0e9c 100644 --- a/src/main/java/org/ecocean/security/Collaboration.java +++ b/src/main/java/org/ecocean/security/Collaboration.java @@ -368,9 +368,9 @@ public static String getNotificationsWidgetHtml(HttpServletRequest request, // e.printStackTrace(); } if (n > 0) - notif = "
" + - collabProps.getProperty("notifications") + " " + - n + "
"; + notif = + "
" + + " " + n + "
"; return notif; } diff --git a/src/main/java/org/ecocean/servlet/ServletUtilities.java b/src/main/java/org/ecocean/servlet/ServletUtilities.java index f190e461fb..cdb402b41e 100644 --- a/src/main/java/org/ecocean/servlet/ServletUtilities.java +++ b/src/main/java/org/ecocean/servlet/ServletUtilities.java @@ -44,9 +44,113 @@ import javax.servlet.http.Cookie; import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.commons.text.WordUtils; +import org.ecocean.CommonConfiguration; +import org.ecocean.ContextConfiguration; +import org.ecocean.Organization; +import org.ecocean.servlet.ServletUtilities; +import org.ecocean.Shepherd; +import org.ecocean.ShepherdProperties; +import org.ecocean.User; +import org.ecocean.Util; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ServletUtilities { public static String getHeader(HttpServletRequest request) { + String context = "context0"; + + context = ServletUtilities.getContext(request); + String langCode = ServletUtilities.getLanguageCode(request); + Properties props = new Properties(); + props = ShepherdProperties.getProperties("header.properties", langCode, context); + // System.out.println("props" + props); + String urlLoc = "//" + CommonConfiguration.getURLLocation(request); + String pageTitle = (String)request.getAttribute("pageTitle"); // allows custom override from calling jsp (must + String siteName = "wildbook"; + try { + // System.out.println("getting site name "); + String name = props.getProperty("siteName"); + // System.out.println("site name is " + name); + if (name != null) { + siteName = name; + } + } catch (Exception e) { + System.out.println("Failed to get siteName property from props:"); + e.printStackTrace(); + } + // set BEFORE include:header) + if (pageTitle == null) { + pageTitle = CommonConfiguration.getHTMLTitle(context); + } else { + pageTitle = CommonConfiguration.getHTMLTitle(context) + " | " + pageTitle; + } + String username = null; + User user = null; + String profilePhotoURL = urlLoc + "/images/empty_profile.jpg"; + // we use this arg bc we can only log out *after* including the header on + // logout.jsp. this way we can still show the logged-out view in the header + boolean loggingOut = Util.requestHasVal(request, "loggedOut"); + String notifications = ""; + // check if user is logged in and has pending notifications + if (request.getUserPrincipal() != null) { + Shepherd myShepherd = new Shepherd(context); + myShepherd.setAction("header.jsp"); + myShepherd.beginDBTransaction(); + try { + notifications = Collaboration.getNotificationsWidgetHtml(request, myShepherd); + if (request.getUserPrincipal() != null && !loggingOut) { + user = myShepherd.getUser(request); + username = (user != null) ? user.getUsername() : null; + if (user.getUserImage() != null) { + profilePhotoURL = "/" + CommonConfiguration.getDataDirectoryName(context) + + "/users/" + user.getUsername() + "/" + + user.getUserImage().getFilename(); + } + } + } catch (Exception e) { + e.printStackTrace(); + myShepherd.closeDBTransaction(); + } finally { + myShepherd.rollbackDBTransaction(); + myShepherd.closeDBTransaction(); + } + } + List supportedLanguages = CommonConfiguration.getIndexedPropertyValues("language", + context); + int numSupportedLanguages = supportedLanguages.size(); + String selectedLangCode = "en"; + Cookie[] cookies = request.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if ("wildbookLangCode".equals(cookie.getName())) { + selectedLangCode = cookie.getValue(); + break; + } + } + } + String selectedImgURL = ""; + if (selectedLangCode != null) { + selectedImgURL = "//" + CommonConfiguration.getURLLocation(request) + "/images/flag_" + + selectedLangCode + ".gif"; + } + StringBuilder htmlBuilder = new StringBuilder(); + for (int h = 0; h < numSupportedLanguages; h++) { + String myLang = supportedLanguages.get(h); + String langName = CommonConfiguration.getProperty(myLang, context); + String imgURL = "//" + CommonConfiguration.getURLLocation(request) + "/images/flag_" + + myLang + ".gif"; + htmlBuilder.append("
") + .append("\"Flag\"") + .append(langName) + .append("
"); + } + String languageString = htmlBuilder.toString(); + try { FileReader fileReader = new FileReader(findResourceOnFileSystem( "servletResponseTemplate.htm")); @@ -60,15 +164,22 @@ public static String getHeader(HttpServletRequest request) { buffread.close(); templateFile = SBreader.toString(); - String context = getContext(request); + String templateContext = getContext(request); // process the CSS string templateFile = templateFile.replaceAll("CSSURL", - CommonConfiguration.getCSSURLLocation(request, context)); + CommonConfiguration.getCSSURLLocation(request, templateContext)); // set the top header graphic templateFile = templateFile.replaceAll("TOPGRAPHIC", - CommonConfiguration.getURLToMastheadGraphic(context)); + CommonConfiguration.getURLToMastheadGraphic(templateContext)); + + templateFile = templateFile.replaceAll("SITE_NAME", siteName); + templateFile = templateFile.replaceAll("USER_NAME", username); + templateFile = templateFile.replaceAll("NOTIFICATION_DETAILS", notifications); + templateFile = templateFile.replace("LANGUAGE_SELECTOR", languageString); + templateFile = templateFile.replace("SELECTED_IMAGE_URL", selectedImgURL); + templateFile = templateFile.replace("PROFILE_PHOTO_URL", profilePhotoURL); int end_header = templateFile.indexOf("INSERT_HERE"); return (templateFile.substring(0, end_header)); @@ -110,10 +221,11 @@ public static String getFooter(String context) { /** * Inform (via email) researchers who've logged an interest in encounter. - * @param request servlet request + * + * @param request servlet request * @param encounterNumber ID of encounter to inform about - * @param message message to include in email notification - * @param context webapp context + * @param message message to include in email notification + * @param context webapp context */ public static void informInterestedParties(HttpServletRequest request, String encounterNumber, String message, String context) { @@ -150,10 +262,11 @@ public static void informInterestedParties(HttpServletRequest request, String en /** * Inform (via email) researchers who've logged an interest in individual. - * @param request servlet request + * + * @param request servlet request * @param individualID ID of individual to inform about - * @param message message to include in email notification - * @param context webapp context + * @param message message to include in email notification + * @param context webapp context */ public static void informInterestedIndividualParties(HttpServletRequest request, String individualID, String message, String context) { @@ -363,7 +476,9 @@ public static boolean isUserAuthorizedForEncounter(Encounter enc, HttpServletReq myShepherd.beginDBTransaction(); try { isOwner = isUserAuthorizedForEncounter(enc, request, myShepherd); - } catch (Exception e) { e.printStackTrace(); } finally { + } catch (Exception e) { + e.printStackTrace(); + } finally { myShepherd.rollbackAndClose(); } return isOwner; @@ -382,10 +497,14 @@ public static boolean isUserAuthorizedForEncounter(Encounter enc, HttpServletReq // user-specific checks else if ((enc.getSubmitterID() != null) && (request.getRemoteUser() != null)) { // allow access to public encounters - if (enc.getSubmitterID().equals("public")) return true; + if (enc.getSubmitterID().equals("public")) + return true; // if the current user owns the Encounter, they obviously have permission - if (enc.getSubmitterID().equals(request.getRemoteUser())) { isOwner = true; } - // if the current user is the orgAdmin for the other user, they can ave permission + if (enc.getSubmitterID().equals(request.getRemoteUser())) { + isOwner = true; + } + // if the current user is the orgAdmin for the other user, they can ave + // permission else if (request.isUserInRole("orgAdmin") && myShepherd.getUser(enc.getSubmitterID()) != null) { User encounterOwner = myShepherd.getUser(enc.getSubmitterID()); @@ -395,22 +514,28 @@ else if (request.isUserInRole("orgAdmin") && if (encounterOwnerOrgs != null && encounterOwnerOrgs.size() > 0 && requesterOrgs != null && requesterOrgs.size() > 0) { for (Organization org : encounterOwnerOrgs) { - if (requesterOrgs.contains(org)) { isOwner = true; } + if (requesterOrgs.contains(org)) { + isOwner = true; + } } } } } // check other cases // ---------------- - // if the current user has a location ID-specific role matching the location ID of this Encounter, they are authorized + // if the current user has a location ID-specific role matching the location ID + // of this Encounter, they are authorized if (!isOwner && enc.getLocationCode() != null && request.isUserInRole(enc.getLocationCode())) { isOwner = true; } // if the current user is in a collaboration with the Encounter owner - if (!isOwner && Collaboration.canEditEncounter(enc, request)) { return true; } + if (!isOwner && Collaboration.canEditEncounter(enc, request)) { + return true; + } // allow WDP edit stenella frontalis cit sci encounters - // TODO make a mmore resonable way for researchers to ID and edit cit sci submissions + // TODO make a mmore resonable way for researchers to ID and edit cit sci + // submissions if (!isOwner && "wdp".equals(request.getUserPrincipal().getName())) { List users = enc.getSubmitters(); boolean researcherSubmitted = false; @@ -425,7 +550,9 @@ else if (request.isUserInRole("orgAdmin") && } } } - } catch (Exception e) { e.printStackTrace(); } + } catch (Exception e) { + e.printStackTrace(); + } return isOwner; } @@ -448,7 +575,9 @@ public static boolean isUserAuthorizedForIndividual(MarkedIndividual indy, myShepherd.beginDBTransaction(); try { isOwner = isUserAuthorizedForIndividual(indy, request, myShepherd); - } catch (Exception e) { e.printStackTrace(); } finally { + } catch (Exception e) { + e.printStackTrace(); + } finally { myShepherd.rollbackAndClose(); } return isOwner; @@ -483,7 +612,9 @@ public static boolean isUserAuthorizedForOccurrence(Occurrence occur, myShepherd.beginDBTransaction(); try { isOwner = isUserAuthorizedForOccurrence(occur, request, myShepherd); - } catch (Exception e) { e.printStackTrace(); } finally { + } catch (Exception e) { + e.printStackTrace(); + } finally { myShepherd.rollbackAndClose(); } return isOwner; @@ -501,7 +632,9 @@ public static boolean isUserAuthorizedForImportTask(ImportTask occ, HttpServletR return true; } // quick collaboration check between current user and bulk import owner - // if(occ.getCreator() !=null && Collaboration.canCollaborate(request.getUserPrincipal().getName(), occ.getCreator().getUsername(), + // if(occ.getCreator() !=null && + // Collaboration.canCollaborate(request.getUserPrincipal().getName(), + // occ.getCreator().getUsername(), // myShepherd.getContext()))return true; if (request.getUserPrincipal() != null && request.getUserPrincipal().getName() != null && occ.getCreator() != null && @@ -510,12 +643,16 @@ public static boolean isUserAuthorizedForImportTask(ImportTask occ, HttpServletR request.getUserPrincipal().getName(), occ.getCreator().getUsername()); if (collab != null && collab.getState() != null && (collab.getState().equals(Collaboration.STATE_EDIT_PRIV) || - collab.getState().equals(Collaboration.STATE_APPROVED))) return true; + collab.getState().equals(Collaboration.STATE_APPROVED))) + return true; } // quick orgAdminCheck - // if this user is the orgAdmin for the bulk import's uploading user, they can see it + // if this user is the orgAdmin for the bulk import's uploading user, they can + // see it if (ServletUtilities.isCurrentUserOrgAdminOfTargetUser(occ.getCreator(), request, - myShepherd)) { return true; } + myShepherd)) { + return true; + } } return false; } @@ -523,7 +660,9 @@ public static boolean isUserAuthorizedForImportTask(ImportTask occ, HttpServletR public static boolean isUserAuthorizedForOccurrence(Occurrence occur, HttpServletRequest request, Shepherd myShepherd) { if (request.getUserPrincipal() != null) { - if (request.isUserInRole("admin")) { return true; } + if (request.isUserInRole("admin")) { + return true; + } ArrayList encounters = occur.getEncounters(); int numEncs = encounters.size(); for (int y = 0; y < numEncs; y++) { @@ -560,36 +699,38 @@ public static String cleanFileName(String myString) { return myString.replaceAll("[^a-zA-Z0-9\\.\\-]", "_"); } - /*public static String cleanFileName(String aTagFragment) { - final StringBuffer result = new StringBuffer(); - - final StringCharacterIterator iterator = new StringCharacterIterator(aTagFragment); - char character = iterator.current(); - while (character != CharacterIterator.DONE) { - if (character == '<') { - result.append("_"); - } else if (character == '>') { - result.append("_"); - } else if (character == '\"') { - result.append("_"); - } else if (character == '\'') { - result.append("_"); - } else if (character == '\\') { - result.append("_"); - } else if (character == '&') { - result.append("_"); - } else if (character == ' ') { - result.append("_"); - } else if (character == '#') { - result.append("_"); - } else { - //the char is not a special one - //add it to the result as is result.append(character); - } - character = iterator.next(); - } - return result.toString(); - } + /* + * public static String cleanFileName(String aTagFragment) { + * final StringBuffer result = new StringBuffer(); + * + * final StringCharacterIterator iterator = new + * StringCharacterIterator(aTagFragment); + * char character = iterator.current(); + * while (character != CharacterIterator.DONE) { + * if (character == '<') { + * result.append("_"); + * } else if (character == '>') { + * result.append("_"); + * } else if (character == '\"') { + * result.append("_"); + * } else if (character == '\'') { + * result.append("_"); + * } else if (character == '\\') { + * result.append("_"); + * } else if (character == '&') { + * result.append("_"); + * } else if (character == ' ') { + * result.append("_"); + * } else if (character == '#') { + * result.append("_"); + * } else { + * //the char is not a special one + * //add it to the result as is result.append(character); + * } + * character = iterator.next(); + * } + * return result.toString(); + * } */ public static String getEncounterUrl(String encID, HttpServletRequest request) { return (CommonConfiguration.getServerURL(request) + "/encounters/encounter.jsp?number=" + @@ -664,13 +805,16 @@ public static String getContext(HttpServletRequest request) { // this can be used for debugging and takes precedence if (request.getParameter("context") != null) { // get the available contexts - // System.out.println("Checking for a context: "+request.getParameter("context")); + // System.out.println("Checking for a context: + // "+request.getParameter("context")); if (contexts.containsKey((request.getParameter("context") + "DataDir"))) { - // System.out.println("Found a request context: "+request.getParameter("context")); + // System.out.println("Found a request context: + // "+request.getParameter("context")); return request.getParameter("context"); } } - // the request cookie is the next thing we check. this should be the primary means of figuring context out + // the request cookie is the next thing we check. this should be the primary + // means of figuring context out Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { @@ -679,14 +823,17 @@ public static String getContext(HttpServletRequest request) { } } } - // finally, we will check the URL vs values defined in context.properties to see if we can set the right context + // finally, we will check the URL vs values defined in context.properties to see + // if we can set the right context String currentURL = request.getServerName(); for (int q = 0; q < numContexts; q++) { String thisContext = "context" + q; List domainNames = ContextConfiguration.getContextDomainNames(thisContext); int numDomainNames = domainNames.size(); for (int p = 0; p < numDomainNames; p++) { - if (currentURL.indexOf(domainNames.get(p)) != -1) { return thisContext; } + if (currentURL.indexOf(domainNames.get(p)) != -1) { + return thisContext; + } } } return context; @@ -712,7 +859,8 @@ public static String getLanguageCode(HttpServletRequest request) { return request.getParameter("langCode"); } } - // the request cookie is the next thing we check. this should be the primary means of figuring langCode out + // the request cookie is the next thing we check. this should be the primary + // means of figuring langCode out Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { @@ -723,8 +871,10 @@ public static String getLanguageCode(HttpServletRequest request) { } } } - // finally, we will check the URL vs values defined in context.properties to see if we can set the right context - // TBD - future - detect browser supported language codes and locale from the HTTPServletRequest object + // finally, we will check the URL vs values defined in context.properties to see + // if we can set the right context + // TBD - future - detect browser supported language codes and locale from the + // HTTPServletRequest object return langCode; } @@ -734,26 +884,31 @@ public static String dataDir(String context, String rootWebappPath) { File shepherdDataDir = new File(webappsDir, CommonConfiguration.getDataDirectoryName(context)); - if (!shepherdDataDir.exists()) { shepherdDataDir.mkdirs(); } + if (!shepherdDataDir.exists()) { + shepherdDataDir.mkdirs(); + } return shepherdDataDir.getAbsolutePath(); } -// like above, but can pass a subdir to append + // like above, but can pass a subdir to append public static String dataDir(String context, String rootWebappPath, String subdir) { return dataDir(context, rootWebappPath) + File.separator + subdir; } -/* - //like above, but only need request passed public static String dataDir(HttpServletRequest request) { - String context = "context0"; - context = ServletUtilities.getContext(request); - //String rootWebappPath = request.getServletContext().getRealPath("/"); // only in 3.0?? - //String rootWebappPath = request.getSession(true).getServlet().getServletContext().getRealPath("/"); - ServletContext s = request.getServletContext(); - String rootWebappPath = "xxxxxx"; - return dataDir(context, rootWebappPath); - } - */ + /* + * //like above, but only need request passed public static String + * dataDir(HttpServletRequest request) { + * String context = "context0"; + * context = ServletUtilities.getContext(request); + * //String rootWebappPath = request.getServletContext().getRealPath("/"); // + * only in 3.0?? + * //String rootWebappPath = + * request.getSession(true).getServlet().getServletContext().getRealPath("/"); + * ServletContext s = request.getServletContext(); + * String rootWebappPath = "xxxxxx"; + * return dataDir(context, rootWebappPath); + * } + */ private static String loadOverrideText(String shepherdDataDir, String fileName, String langCode) { // System.out.println("Starting loadOverrideProps"); @@ -774,10 +929,13 @@ private static String loadOverrideText(String shepherdDataDir, String fileName, // System.out.println("The fix abs path is: "+configDir.getAbsolutePath()); } // System.out.println("ShepherdProps: "+configDir.getAbsolutePath()); - if (!configDir.exists()) { configDir.mkdirs(); } + if (!configDir.exists()) { + configDir.mkdirs(); + } File configFile = new File(configDir, fileName); if (configFile.exists()) { - // System.out.println("ShepherdProps: "+"Overriding default properties with " + configFile.getAbsolutePath()); + // System.out.println("ShepherdProps: "+"Overriding default properties with " + + // configFile.getAbsolutePath()); FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream(configFile); @@ -804,7 +962,9 @@ private static String loadOverrideText(String shepherdDataDir, String fileName, } public static String handleNullString(Object obj) { - if (obj == null) { return ""; } + if (obj == null) { + return ""; + } return obj.toString(); } @@ -843,18 +1003,22 @@ public static List getIndexedParameters(String key, HttpServletRequest r for (int i = 0; i < 100000; i++) { // hundred thousand seems like a reasonable upper limit right? String val = request.getParameter(key + i); - if (Util.stringExists(val)) vals.add(val); - else return vals; + if (Util.stringExists(val)) + vals.add(val); + else + return vals; } return vals; } public static String getParameterOrAttribute(String name, HttpServletRequest request) { - if (name == null) return null; + if (name == null) + return null; String result = request.getParameter(name); if (result == null) { Object attr = request.getAttribute(name); - if (attr != null) result = attr.toString(); + if (attr != null) + result = attr.toString(); } return result; } @@ -865,9 +1029,11 @@ public static String getParameterOrAttributeOrSessionAttribute(String name, if (result == null) { Object attr = request.getAttribute(name); - if (attr != null) result = attr.toString(); + if (attr != null) + result = attr.toString(); } - if (result == null) result = getSessionAttribute(name, request); + if (result == null) + result = getSessionAttribute(name, request); return result; } @@ -875,11 +1041,12 @@ public static String getSessionAttribute(String name, HttpServletRequest request String stringAns = null; Object attr = request.getSession().getAttribute(name); - if (attr != null) stringAns = attr.toString(); + if (attr != null) + stringAns = attr.toString(); return stringAns; } -// handy "let anyone do anything (?) cors stuff + // handy "let anyone do anything (?) cors stuff public static void doOptions(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setHeader("Access-Control-Allow-Origin", "*"); @@ -889,9 +1056,10 @@ public static void doOptions(HttpServletRequest request, HttpServletResponse res request.getHeader("Access-Control-Request-Headers")); } -/* see webapps/captchaExample.jsp for implementation */ + /* see webapps/captchaExample.jsp for implementation */ -// note: this only handles single-widget (per page) ... if we need multiple, will have to extend things here + // note: this only handles single-widget (per page) ... if we need multiple, + // will have to extend things here public static String captchaWidget(HttpServletRequest request) { return captchaWidget(request, null); } @@ -916,14 +1084,15 @@ public static String captchaWidget(HttpServletRequest request, String params) { "
"; } -// https://developers.google.com/recaptcha/docs/verify + // https://developers.google.com/recaptcha/docs/verify public static boolean captchaIsValid(HttpServletRequest request) { return captchaIsValid(getContext(request), request.getParameter("g-recaptcha-response"), request.getRemoteAddr()); } public static boolean captchaIsValid(String context, String uresp, String remoteIP) { - if (context == null) context = "context0"; + if (context == null) + context = "context0"; Properties recaptchaProps = ShepherdProperties.getProperties("recaptcha.properties", "", context); if (recaptchaProps == null) { @@ -964,12 +1133,15 @@ public static boolean captchaIsValid(String context, String uresp, String remote return gresp.optBoolean("success", false); } -// this takes into account that we might be going thru nginx (etc?) as well + // this takes into account that we might be going thru nginx (etc?) as well public static String getRemoteHost(HttpServletRequest request) { - if (request == null) return null; - // these all seem to be *possible* headers from nginx (or other proxies?) but we standardize on "x-real-ip" + if (request == null) + return null; + // these all seem to be *possible* headers from nginx (or other proxies?) but we + // standardize on "x-real-ip" // x-real-ip, x-forwarded-for, x-forwarded-host - if (request.getHeader("x-real-ip") != null) return request.getHeader("x-real-ip"); + if (request.getHeader("x-real-ip") != null) + return request.getHeader("x-real-ip"); return request.getRemoteHost(); } @@ -981,7 +1153,8 @@ public static void importJsp(String filename, HttpServletRequest request, request.getRequestDispatcher(filename).include(request, response); } -// used to determine if we want to apply a custom UI style, e.g. for IndoCet or the New England Aquarium to a web page + // used to determine if we want to apply a custom UI style, e.g. for IndoCet or + // the New England Aquarium to a web page public static boolean useCustomStyle(HttpServletRequest request, String orgName) { // check url for "organization=____" arg String organization = request.getParameter("organization"); @@ -993,19 +1166,25 @@ public static boolean useCustomStyle(HttpServletRequest request, String orgName) if (cookieOrg != null && orgName.toLowerCase().equals(cookieOrg.toLowerCase())) { return true; } - // The checks further below will also return true _right after logging out_ so we need this step - if (Util.requestHasVal(request, "logout")) return false; - // Shepherd handling w 'finally' to ensure we close the dbconnection after return. + // The checks further below will also return true _right after logging out_ so + // we need this step + if (Util.requestHasVal(request, "logout")) + return false; + // Shepherd handling w 'finally' to ensure we close the dbconnection after + // return. Shepherd myShepherd = Shepherd.newActiveShepherd(request, "ServletUtilities.useCustomStyle"); try { // check user affiliation User user = myShepherd.getUser(request); - if (user == null) return false; - if (user.hasAffiliation(orgName)) return true; + if (user == null) + return false; + if (user.hasAffiliation(orgName)) + return true; // check organization object Organization org = myShepherd.getOrganizationByName(orgName); - if (org == null) return false; + if (org == null) + return false; return org.hasMember(user); } finally { myShepherd.rollbackAndClose(); diff --git a/src/main/resources/bundles/en/header.properties b/src/main/resources/bundles/en/header.properties index 5fc2eb4761..72b0e8bb2b 100755 --- a/src/main/resources/bundles/en/header.properties +++ b/src/main/resources/bundles/en/header.properties @@ -1,4 +1,4 @@ - +siteName = Flukebook manageUsers = Manage My Accounts searchPlaceholder = nickname, id, site, encounter nr., etc. home = Home @@ -53,6 +53,24 @@ myAccount = My Account batchUpload = Batch Upload userAgreement = User Agreement +aboutWildbook = About Wildbook +contactUs = Contact Us +myEncounters = My Encounters +myData = My Data +myApprovedAnimals = My Approved Animals +myUnapprovedAnimals = My Unapproved Animals +myUnidentifiableAnimals = My Unidentifiable Animals +myIndividuals = My Individuals +mySightings = My Sightings +myBulkImports = My Bulk Imports +myProjects = My Projects +sightings = Sightings +animals = Animals +individualGallery = Individual Gallery +manageMyAccounts = Manage My Accounts +libraryAdministration = Library Administration +softwareDocumentation = Software Documentation +bulkImportLogs = Bulk Import Logs aboutYourProject = About Flukebook howToPhotograph = How To Photograph states = By State diff --git a/src/main/resources/bundles/es/header.properties b/src/main/resources/bundles/es/header.properties index f435bd35eb..7fbfaf53c4 100755 --- a/src/main/resources/bundles/es/header.properties +++ b/src/main/resources/bundles/es/header.properties @@ -1,4 +1,4 @@ - +siteName = Flukebook manageUsers = Administrar mis cuentas searchPlaceholder = Apodo, id, sitio, encuentro... home = Inicio diff --git a/src/main/resources/bundles/fr/header.properties b/src/main/resources/bundles/fr/header.properties index 7aa48fb538..e22fd3c543 100644 --- a/src/main/resources/bundles/fr/header.properties +++ b/src/main/resources/bundles/fr/header.properties @@ -1,4 +1,4 @@ - +siteName = Flukebook manageUsers = Gérer mes comptes searchPlaceholder = surnom, id, site, rencontre, n\u00b0, etc. home = Accueil diff --git a/src/main/resources/bundles/it/header.properties b/src/main/resources/bundles/it/header.properties index f7935c3389..9cd0339a96 100644 --- a/src/main/resources/bundles/it/header.properties +++ b/src/main/resources/bundles/it/header.properties @@ -1,4 +1,4 @@ - +siteName = Flukebook searchPlaceholder = nickname, id, sito, nr. incontro, ecc. home = home learn = scopri diff --git a/src/main/resources/servletResponseTemplate.htm b/src/main/resources/servletResponseTemplate.htm index 7e63cbb900..9bdf0549f8 100755 --- a/src/main/resources/servletResponseTemplate.htm +++ b/src/main/resources/servletResponseTemplate.htm @@ -1,168 +1,334 @@ - - - Wildbook - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +
+

Action results

+

INSERT_HERE

+ +
+ + + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 50f1cd10e9..136ad73eec 100755 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -52,7 +52,7 @@ authcBasicWildbook = org.ecocean.security.WildbookBasicHttpAuthenticationFilter - authc.loginUrl = /login.jsp + authc.loginUrl = /react #this application will use all the default #filters (see link above) diff --git a/src/main/webapp/css/footer.css b/src/main/webapp/css/footer.css new file mode 100644 index 0000000000..cb9a395699 --- /dev/null +++ b/src/main/webapp/css/footer.css @@ -0,0 +1,40 @@ + +.footer-font { + font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; +} + +.footer-link { + color: inherit; + text-decoration: none; +} +.footer-link:hover { + text-decoration: none; +} +.footer-container { + height: 200px; + background-color: #CDE0FE; + padding-left: 30%; + padding-right: 30%; + padding-top: 10px; + margin: 0; + width: 100vw; +} +.footer-col { + display: flex; + flex-direction: column; + padding: 0; +} +.footer-text { + color: black !important; + text-decoration: none; + font-size: 16px; + font-weight: 400; + margin-bottom: 5px; + display: block; +} +.footer-row { + height: 150px; + display: flex; + justify-content: space-between; + gap: 15px; +} \ No newline at end of file diff --git a/src/main/webapp/css/header.css b/src/main/webapp/css/header.css new file mode 100644 index 0000000000..437f962b18 --- /dev/null +++ b/src/main/webapp/css/header.css @@ -0,0 +1,219 @@ +/* .navbar .dropdown-menu { + font-size: 16px; + background-color: white; +} */ + +.navbar .dropdown-toggle { + color: white !important; + font-size: 16px !important; + white-space: nowrap; +} + +.navbar-collapse { + display: flex; + justify-content: center; +} + +.container { + position: relative; +} + +.navbar-nav { + display: flex; + padding-left: 20px; + padding-right: 50px; + flex-grow: 1; + justify-content: space-between; + width: 100%; +} + +.navbar-nav > li { + flex-grow: 1; + text-align: center; +} + +.navbar .navbar-nav > li > a:hover{ + background-color: inherit; + border-bottom: 2px solid white; +} + +.navbar .navbar-nav > li > a { + border-bottom: 2px solid transparent; +} + +.navbar .navbar-nav .dropdown-menu > li> a { + font-weight: normal; +} + +.navbar .dropdown-menu > li> a:hover{ + background-color: #CCF0FF !important; + box-sizing: border-box; + background-image: none; +} +/* .navbar .navbar-nav .dropdown-menu > li:hover{ + background-color: red !important; + border-bottom: 2px solid green; + box-sizing: border-box; +} */ + +.dropdown-submenu { + position: relative; +} + +.dropdown-submenu .dropdown-menu { + top: 0; + left: 100%; + margin-top: -1px; +} + +.dropdown-submenu:hover .dropdown-menu { + display: block; +} + +.custom-select-wrapper { + position: relative; + width: 65px; + height: 35px; + border-radius: 30px; + background-color: rgba(255, 255, 255, 0.25); + display: flex; + align-items: center; + justify-content: center; + margin-left: 10px; + margin-right:10px; +} +.custom-select { + position: relative; + cursor: pointer; +} +.custom-select-selected { + margin-top: 6px; + width: 40px; + display: flex; + flex-direction: row; + justify-content: space-between; +} +.selected-item{ + /* margin-top: 5px; */ + width: 20px; + height: 20px; + background-repeat: no-repeat; +} +.custom-select-items { + position: absolute; + top: 100%; + left: 0; + z-index: 99; + width: 150px; + border: 1px solid #ccc; + background: white; + color: black; + padding: 10px; + border-radius: 3px; + /* display: none; */ +} + +.custom-select-items div { + /* border-color: red; */ + background-repeat: no-repeat; + background-position: 10px center; + padding-top: 10px; +} +.hidden { + display: none; +} + +.profile-icon { + width: 35px; + height: 35px; + border-radius: 50%; + background-size: cover; + cursor: pointer; +} + +.dropdown-menu { + top: 100%; + list-style: none; + margin: 0; + padding: 3px; + display: none; + position: absolute; + border-radius: 5px; + background-color: white; +} + +.profile-wrapper{ + position: relative; + width: 40px; + height: 40px; + display: flex; + align-items: center; + margin-left: 35px; +} + +.profile-wrapper:hover .dropdown-menu { + display: block; +} + +.dropdown-menu:hover { + display: block; +} + +.dropdown-menu li a { + display: block; + padding: 8px; + text-decoration: none; + color: black; + background-color: white; +} + +.dropdown-menu li a:hover { + background-color: #f0f0f0; +} + +.secondary-nav { + display: flex; + flex-direction: row; +} + +.site-name { + /* width: 250px; */ + /* height: 100%; */ + max-height: 60px; + margin-right: 100px; + font-size: 24px; + display: flex; + align-items: center; + justify-content: center; + text-decoration: none; +} + +.nav-brand { + min-width: 30px; + min-height: 30px; + max-width: 60px; + max-height: 60px; + margin-left: auto; + margin-right: 10px; + display: block !important; + /* background: url(../cust/mantamatcher/img/flukebook_logo_white.svg) no-repeat center; */ +} + +.site-name:hover { + text-decoration: none; +} + +.search-and-secondary-wrapper { + margin: 0 !important; + display: flex; + flex-direction: row; + align-items: center; + list-style-type: none; + position: relative; +} + + +.header-font { + font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-weight:400; +} \ No newline at end of file diff --git a/src/main/webapp/cust/mantamatcher/img/flukebook_logo_white.svg b/src/main/webapp/cust/mantamatcher/img/flukebook_logo_white.svg index 22ea991873..628e922fe2 100644 --- a/src/main/webapp/cust/mantamatcher/img/flukebook_logo_white.svg +++ b/src/main/webapp/cust/mantamatcher/img/flukebook_logo_white.svg @@ -1,98 +1,8 @@ -image/svg+xml - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/src/main/webapp/cust/mantamatcher/styles/_bootstrap-overrides.less b/src/main/webapp/cust/mantamatcher/styles/_bootstrap-overrides.less index 4038befd84..51922a3c80 100644 --- a/src/main/webapp/cust/mantamatcher/styles/_bootstrap-overrides.less +++ b/src/main/webapp/cust/mantamatcher/styles/_bootstrap-overrides.less @@ -18,10 +18,10 @@ label { font-weight: normal; } overflow: visible; } -.page-header { margin: 52px 0 26px; } +.page-header { margin: 52px 0 16px; } @media (min-width: @screen-sm) { - .page-header { margin: 47px 0 20px; } + .page-header { margin: 47px 0 0; } } /* nav bar */ @@ -56,15 +56,15 @@ label { font-weight: normal; } background: url(../img/flukebook_logo_white.svg) no-repeat center; } -@media (min-width: @screen-sm) { - .navbar-brand { - height: 80px; - width: 100%; - max-width: 350px; - clear: none; - float: left; - } -} +// @media (min-width: @screen-sm) { +// .navbar-brand { +// height: 60px; +// width: 60px; +// max-width: 60px; +// clear: none; +// float: left; +// } +// } /* removed */ .navbar-default { diff --git a/src/main/webapp/cust/mantamatcher/styles/_bootstrap.less b/src/main/webapp/cust/mantamatcher/styles/_bootstrap.less index 4c4bdeb558..f0e5d259ca 100644 --- a/src/main/webapp/cust/mantamatcher/styles/_bootstrap.less +++ b/src/main/webapp/cust/mantamatcher/styles/_bootstrap.less @@ -4325,10 +4325,11 @@ select[multiple].input-group-sm > .input-group-btn > .btn { } .navbar-brand { float: left; - padding: 12px 15px; + padding: 12px 20px; font-size: 32px; line-height: 26px; - height: 50px; + height: 60px; + width: 60px; } .navbar-brand:hover, .navbar-brand:focus { diff --git a/src/main/webapp/cust/mantamatcher/styles/_custom.less b/src/main/webapp/cust/mantamatcher/styles/_custom.less index a5ac9bcaa9..daedc0d0f9 100644 --- a/src/main/webapp/cust/mantamatcher/styles/_custom.less +++ b/src/main/webapp/cust/mantamatcher/styles/_custom.less @@ -375,7 +375,7 @@ form table td, form table th { .search-and-secondary-wrapper { float: right; width: auto; - margin-top: 30px; + // margin-top: 30px; } } diff --git a/src/main/webapp/cust/mantamatcher/styles/_wildbook.less b/src/main/webapp/cust/mantamatcher/styles/_wildbook.less index 2bb4243058..968896d431 100644 --- a/src/main/webapp/cust/mantamatcher/styles/_wildbook.less +++ b/src/main/webapp/cust/mantamatcher/styles/_wildbook.less @@ -1,98 +1,106 @@ - .collab-private { - background-color: #FDD; - } - - .collab-private td { - background-color: transparent !important; - } - - .collab-private .collab-icon { - position: absolute; - left: -15px; - z-index: -1; - width: 13px; - height: 13px; - background: url(../images/lock-icon-tiny.png) no-repeat; - } +.collab-private { + background-color: #FDD; +} + +.collab-private td { + background-color: transparent !important; +} + +.collab-private .collab-icon { + position: absolute; + left: -15px; + z-index: -1; + width: 13px; + height: 13px; + background: url(../images/lock-icon-tiny.png) no-repeat; +} .maincontent { - padding-top: 30px; + padding-top: 30px; } -.flexbox{ - display: flex; - padding-bottom: 0.2em; - justify-content: space-evenly; +.flexbox { + display: flex; + padding-bottom: 0.2em; + justify-content: space-evenly; } -.flex-right-justify{ - align-self: flex-end; - margin: auto; +.flex-right-justify { + align-self: flex-end; + margin: auto; } -.flex-left-justify{ - align-self: flex-start; - margin: auto; + +.flex-left-justify { + align-self: flex-start; + margin: auto; } -.flex-left-justify-no-margin{ - align-self: flex-start; - margin: 0; + +.flex-left-justify-no-margin { + align-self: flex-start; + margin: 0; } + table.project-style { - border: 1px; - border-spacing: 2px; - border-color: gray; - border-collapse: collapse; - background-color: white; + border: 1px; + border-spacing: 2px; + border-color: gray; + border-collapse: collapse; + background-color: white; } + table.project-style th { - border-width: 1px; - padding: 1px; - border-style: solid; - border-color: gray; - background-color: #E6EEEE; - -moz-border-radius: ; - padding-right: 1em; + border-width: 1px; + padding: 1px; + border-style: solid; + border-color: gray; + background-color: #E6EEEE; + -moz-border-radius: ; + padding-right: 1em; } + table.project-style td { - border-width: 1px; - padding: 2px; - border-style: solid; - border-color: gray; - background-color: white; - -moz-border-radius: ; - padding-right: 1em; + border-width: 1px; + padding: 2px; + border-style: solid; + border-color: gray; + background-color: white; + -moz-border-radius: ; + padding-right: 1em; } table.tissueSample { - border: 1px; - border-spacing: 2px; - border-style: hidden; - border-color: gray; - border-collapse: collapse; - background-color: white; + border: 1px; + border-spacing: 2px; + border-style: hidden; + border-color: gray; + border-collapse: collapse; + background-color: white; } + table.tissueSample th { - border-width: 1px; - padding: 1px; - border-style: solid; - border-color: gray; - background-color: #99CCFF; - -moz-border-radius: ; + border-width: 1px; + padding: 1px; + border-style: solid; + border-color: gray; + background-color: #99CCFF; + -moz-border-radius: ; } + table.tissueSample td { - border-width: 1px; - padding: 2px; - border-style: solid; - border-color: gray; - background-color: white; - -moz-border-radius: ; + border-width: 1px; + padding: 2px; + border-style: solid; + border-color: gray; + background-color: white; + -moz-border-radius: ; } -.vm-button, .vm-button:hover { +.vm-button, +.vm-button:hover { /* - background: url(../images/compare-images-icon.png) no-repeat; - width: 69px; - height: 60px; +background: url(../images/compare-images-icon.png) no-repeat; +width: 69px; +height: 60px; */ color: #000; text-decoration: none; @@ -111,6 +119,7 @@ table.tissueSample td { .vm-img-wrapper { position: relative; } + .vm-img-wrapper .vm-button { bottom: -4px; right: -4px; @@ -140,7 +149,7 @@ table.tissueSample td { position: absolute; bottom: 0; right: 0; - background-color: rgba(200,200,200, 0.75); + background-color: rgba(200, 200, 200, 0.75); padding: 2px; } @@ -153,21 +162,21 @@ table.tissueSample td { #dropzone-previews { border-radius: 8px; - background-color: rgba(50,50,50, 0.2); + background-color: rgba(50, 50, 50, 0.2); padding: 10px; min-height: 100px; margin: 0 20px 0 2px; } #dropzone-previews:hover { - background-color: rgba(50,50,50, 0.3); + background-color: rgba(50, 50, 50, 0.3); } .input-file-drop { position: relative; overflow: hidden; border-radius: 8px; - background-color: rgba(50,50,50, 0.2); + background-color: rgba(50, 50, 50, 0.2); padding: 30px 10px 10px 10px; text-align: center; min-width: 50%; @@ -177,7 +186,7 @@ table.tissueSample td { } .input-file-drop:hover { - background-color: rgba(50,50,50, 0.3); + background-color: rgba(50, 50, 50, 0.3); } @@ -207,7 +216,7 @@ table.tissueSample td { .img-watermark { - background-color: rgba(255,255,255,0.3); + background-color: rgba(255, 255, 255, 0.3); position: absolute; top: 75px; left: -25px; @@ -216,7 +225,7 @@ table.tissueSample td { text-align: center; padding: 13px; transform: rotate(-21deg); - color: rgba(0,0,0,0.9); + color: rgba(0, 0, 0, 0.9); } @@ -247,9 +256,11 @@ div.row-lock.new { background: url(../images/lock-icon.png) no-repeat; cursor: pointer; } + div.row-lock.pending { background: url(../images/lock-icon-pending.png) no-repeat; } + div.row-lock.blocked { background: url(../images/lock-icon-no.png) no-repeat; } @@ -270,7 +281,7 @@ tr.no-access:hover td { /* .no-access img { - opacity: 0.5; +opacity: 0.5; } */ @@ -310,45 +321,86 @@ tr.no-access:hover td { .collaboration-failure { color: #A21; } + .collaboration-success { color: #2A4; } #notifications { - font-size: 0.9em; position: absolute; - top: 110px; - left: 10px; + top: 50%; + left: -25px; + transform: translateY(-50%); + border-radius: 50%; + height: 45px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; } -#notifications div { - padding: 4px; - color: rgba(0,0,0,0); - cursor: pointer; - border: 1px solid rgba(0,0,0,0); - border-radius: 3px; +.notification-container { + position: absolute; + top: 40%; + left: -25px; + transform: translateY(-50%); } -#notifications div:hover { - background-color: #DDD; - border-color: #888; - color: rgba(0,0,0,0.5); +#notifications div { + // padding: 4px; + // color: rgba(0,0,0,0); + // cursor: pointer; + // border: 1px solid rgba(0,0,0,0); + // border-radius: 3px; + background-color: rgba(255, 255, 255, 0.25); + border: none; + border-radius: 50%; + width: 35px; + height: 35px; + display: flex; + align-items: center; + justify-content: center; + position: relative; + padding: 0; } +// #notifications div:hover { +// background-color: #DDD; +// border-color: #888; +// color: rgba(0,0,0,0.5); +// } + .notification-pill { + // color: #FFF; + // background-color: yellow; + // border-radius: 7px; + // font-weight: bold; + // padding: 1px 5px 1px 5px; + // margin: 1px 3px 1px 3px; + // opacity: 0.6; + color: #FFF; - background-color: #F12; - border-radius: 7px; + font-size: 12px; + background-color: red; font-weight: bold; - padding: 1px 5px 1px 5px; - margin: 1px 3px 1px 3px; - opacity: 0.6; -} + width: 12px; + height: 12px; + position: absolute; + top: 22px; + left: 22px; + padding: 0 4px; + font-size: 0.5rem; + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; -#notifications div:hover .notification-pill { - opacity: 1.0; } +// #notifications div:hover .notification-pill { +// opacity: 1.0; +// } + .merge-action-feedback { font-weight: 500; @@ -356,7 +408,8 @@ tr.no-access:hover td { } -.collaboration-invite-notification, .merge-notification { +.collaboration-invite-notification, +.merge-notification { margin: 3px; padding: 1px 3px 1px 3px; background-color: #DDD; @@ -364,23 +417,27 @@ tr.no-access:hover td { line-height: 3.5em; height: 60px; } -.collaboration-invite-notification:hover, .merge-notification:hover { + +.collaboration-invite-notification:hover, +.merge-notification:hover { background-color: #DDE; } -.collaboration-invite-notification input, .merge-notification input { + +.collaboration-invite-notification input, +.merge-notification input { padding: 0px 4px !important; float: right; } /* - //h += "
to " + c.getUsername2() + "" + c.getState() + "
"; + //h += "
to " + c.getUsername2() + "" + c.getState() + "
"; */ div.collab-list div { padding: 6px; width: 100%; - background-color: rgba(100,100,100,0.2); + background-color: rgba(100, 100, 100, 0.2); margin: 5px; } @@ -408,7 +465,7 @@ div.collab-list div.mine span.who b { } .collab-button { - height:58px; + height: 58px; width: 30%; } @@ -443,7 +500,7 @@ div.collab-log div.scrollbox { div.collab-log div.logrow { font-size: 0.9em; - background-color: rgba(0,0,0,0.2); + background-color: rgba(0, 0, 0, 0.2); margin: 2px; padding: 2px; } @@ -453,7 +510,8 @@ div.collab-log span { padding: 2px; } -.collab-table { /*leave room for lock icon*/ +.collab-table { + /*leave room for lock icon*/ width: 785px; margin-left: 25px; } @@ -461,9 +519,11 @@ div.collab-log span { div.state-initialized span.state { background-color: #AA1; } + div.state-rejected span.state { background-color: #821; } + div.state-approved span.state { background-color: #281; } @@ -485,122 +545,142 @@ div.state-approved span.state { /* CSS for MantaMatcher algorithm results */ #mma .sectionTitle { - font-weight: bold; + font-weight: bold; } + #mma .subSection { - clear: both; - font-size: 0.9em; + clear: both; + font-size: 0.9em; } + #mma .subSectionTitle { - background-color: #f0f0f0; - padding: 0.5em; - font-style: italic; -} -#mma .subSubSection { + background-color: #f0f0f0; + padding: 0.5em; + font-style: italic; } + +#mma .subSubSection {} + #mma .subSubSectionTitle { - background-color: #f0f0f0; - padding: 0.5em; - font-style: italic; + background-color: #f0f0f0; + padding: 0.5em; + font-style: italic; } + #mma .featureRegion { - width: 100%; + width: 100%; } + #mma .featureRegionImage { - float: left; - width: 380px; - padding: 0 10px 0 0; + float: left; + width: 380px; + padding: 0 10px 0 0; } + #mma .featureRegionImage img { - max-width: 100%; - height: auto; + max-width: 100%; + height: auto; } + #mma .featureRegionResults { - float: right; - width: 410px; - padding: 0 0 0 10px; + float: right; + width: 410px; + padding: 0 0 0 10px; } -#mma .resultsGlobal, #mma .resultsRegional { - margin-top: 1em; - padding: 5px 10px; - background-color: #f0f0f0 + +#mma .resultsGlobal, +#mma .resultsRegional { + margin-top: 1em; + padding: 5px 10px; + background-color: #f0f0f0 } + #mma .featureRegionResults .smallish { - white-space: nowrap; - text-align: right; + white-space: nowrap; + text-align: right; } .socialphoto { - margin: 5px; - padding: 5px; + margin: 5px; + padding: 5px; } .socialphoto.selected { - background-color: greenyellow; + background-color: greenyellow; } -.borderless tbody tr td, .borderless tbody tr th, .borderless thead tr th { - border: none; +.borderless tbody tr td, +.borderless tbody tr th, +.borderless thead tr th { + border: none; } #search-help { - position: absolute; - top: 20px; - padding: 1px 3px; - border-radius: 2px; - left: 0; - background-color: rgba(230, 230, 230, 0.9); - display: none; - } + position: absolute; + top: 20px; + padding: 1px 3px; + border-radius: 2px; + left: 0; + background-color: rgba(230, 230, 230, 0.9); + display: none; +} .ui-autocomplete.ui-menu { z-index: 2000 !important; - } +} // myAccount.jsp custom styles div.state-edit span.state { background-color: green; - } - html body div.collab-list input[type="button"] { - /* - margin-top: 0; - margin-left: 4em; - */ - margin-top: 0; - float: right; - } - html body div.collab-list input[type="button"].no { - margin-left:0; - } - html body div.collab-list input[type="button"].no { - margin-left:0; - } - - html body div.collab-list span.collab-button { - text-align:right; - } +} + +html body div.collab-list input[type="button"] { + /* + margin-top: 0; + margin-left: 4em; + */ + margin-top: 0; + float: right; +} + +html body div.collab-list input[type="button"].no { + margin-left: 0; +} + +html body div.collab-list input[type="button"].no { + margin-left: 0; +} + +html body div.collab-list span.collab-button { + text-align: right; +} + div div div.clear { -clear: both; -margin: 0; -padding: 0; + clear: both; + margin: 0; + padding: 0; } + div.collab-list div.collabRow { -display: table; + display: table; } + div.collab-list div.collabRow span { -display: table-cell; -vertical-align: middle; + display: table-cell; + vertical-align: middle; } + div.collab-list div.collabRow span { -display: table-cell; -vertical-align: middle; + display: table-cell; + vertical-align: middle; } + div.collab-list div.collabRow span.state { -width: 5em; -height: 2em; -text-align: center; + width: 5em; + height: 2em; + text-align: center; } .collab-init-btn { @@ -609,13 +689,13 @@ text-align: center; } .chip { - display: inline-block; - padding: 0 25px; - height: 50px; - font-size: 16px; - line-height: 50px; - border-radius: 25px; - background-color: #f1f1f1; + display: inline-block; + padding: 0 25px; + height: 50px; + font-size: 16px; + line-height: 50px; + border-radius: 25px; + background-color: #f1f1f1; } // end myAccount.jsp custom styles @@ -627,10 +707,11 @@ text-align: center; } .hoverRow tr:hover { - background-color: #e1ddd9; + background-color: #e1ddd9; } + .hoverRow tr:hover td { - background-color: transparent; + background-color: transparent; } #projectDropdownSpan { @@ -658,7 +739,7 @@ text-align: center; .proj-action-btn { padding: 0px 10px; - margin-top:4px; + margin-top: 4px; margin-bottom: 4px; width: 100%; } diff --git a/src/main/webapp/footer.jsp b/src/main/webapp/footer.jsp index 3293220cf9..f66ee22cfe 100755 --- a/src/main/webapp/footer.jsp +++ b/src/main/webapp/footer.jsp @@ -28,28 +28,27 @@ String urlLoc = "//" + CommonConfiguration.getURLLocation(request); %> - + + +
+ + diff --git a/src/main/webapp/header.jsp b/src/main/webapp/header.jsp index 160e36a3b9..37462d0438 100755 --- a/src/main/webapp/header.jsp +++ b/src/main/webapp/header.jsp @@ -31,10 +31,31 @@ java.util.Properties, org.apache.commons.text.WordUtils, org.ecocean.security.Collaboration, - org.ecocean.ContextConfiguration + org.ecocean.ContextConfiguration, + org.slf4j.Logger,org.slf4j.LoggerFactory " %> +<% + if ("logout".equals(request.getParameter("action"))) { + System.out.println("Logging out"); + response.setHeader("Cache-Control", "no-cache"); + response.setHeader("Cache-Control", "no-store"); + response.setDateHeader("Expires", 0); + response.setHeader("Pragma", "no-cache"); + + Logger log = LoggerFactory.getLogger(getClass()); + + if (request.getRemoteUser() != null) { + log.info(request.getRemoteUser() + " logged out."); + } + session.invalidate(); + + response.sendRedirect(request.getContextPath() + "/react/login/"); + return; + } +%> + <% String context="context0"; context=ServletUtilities.getContext(request); @@ -60,41 +81,33 @@ String profilePhotoURL=urlLoc+"/images/empty_profile.jpg"; // we use this arg bc we can only log out *after* including the header on logout.jsp. this way we can still show the logged-out view in the header boolean loggingOut = Util.requestHasVal(request, "loggedOut"); -boolean indocetUser = false; -String organization = request.getParameter("organization"); -if (organization!=null && organization.toLowerCase().equals("indocet")) { - indocetUser = true; -} String notifications=""; //check if user is logged in and has pending notifications if(request.getUserPrincipal()!=null){ - Shepherd myShepherd = new Shepherd(context); - myShepherd.setAction("header.jsp"); - myShepherd.beginDBTransaction(); - try { - - notifications=Collaboration.getNotificationsWidgetHtml(request, myShepherd); - - if(!indocetUser && request.getUserPrincipal()!=null && !loggingOut){ - user = myShepherd.getUser(request); - username = (user!=null) ? user.getUsername() : null; - String orgName = "indocet"; - Organization indocetOrg = myShepherd.getOrganizationByName(orgName); - indocetUser = ((user!=null && user.hasAffiliation(orgName)) || (indocetOrg!=null && indocetOrg.hasMember(user))); - if(user.getUserImage()!=null){ - profilePhotoURL="/"+CommonConfiguration.getDataDirectoryName(context)+"/users/"+user.getUsername()+"/"+user.getUserImage().getFilename(); - } - } - } - catch(Exception e){ - System.out.println("Exception on indocetCheck in header.jsp:"); - e.printStackTrace(); - myShepherd.closeDBTransaction(); - } - finally{ - myShepherd.rollbackDBTransaction(); - myShepherd.closeDBTransaction(); - } + Shepherd myShepherd = new Shepherd(context); + myShepherd.setAction("header.jsp"); + myShepherd.beginDBTransaction(); + try { + + notifications=Collaboration.getNotificationsWidgetHtml(request, myShepherd); + + if(request.getUserPrincipal()!=null && !loggingOut){ + user = myShepherd.getUser(request); + username = (user!=null) ? user.getUsername() : null; + if(user.getUserImage()!=null){ + profilePhotoURL="/"+CommonConfiguration.getDataDirectoryName(context)+"/users/"+user.getUsername()+"/"+user.getUserImage().getFilename(); + } + } + } + catch(Exception e){ + System.out.println("Exception on indocetCheck in header.jsp:"); + e.printStackTrace(); + myShepherd.closeDBTransaction(); + } + finally{ + myShepherd.rollbackDBTransaction(); + myShepherd.closeDBTransaction(); + } } %> @@ -114,6 +127,12 @@ if(request.getUserPrincipal()!=null){ gtag('config', 'UA-30944767-12'); + + @@ -168,13 +180,21 @@ if(request.getUserPrincipal()!=null){ + + + - + + + - <% +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + + + <% if((CommonConfiguration.getProperty("allowSocialMediaLogin", context)!=null)&&(CommonConfiguration.getProperty("allowSocialMediaLogin", context).equals("true"))){ %> @@ -191,8 +211,21 @@ if(request.getUserPrincipal()!=null){ - + + + <% if(user != null && !loggingOut){ %> @@ -200,7 +233,7 @@ if(request.getUserPrincipal()!=null){ $(document).ready(function() - { + { var warningTime = <%= sessionWarningTime %>; // Session warning time in minutes. var activityTimeout = warningTime * 60 * 1000; // Convert warning time to milliseconds. var activityCheckInterval = 1000; // Frequency to check for activity in milliseconds. @@ -329,13 +362,13 @@ if(request.getUserPrincipal()!=null){ - - - - + + + + - + @@ -378,184 +411,18 @@ if(request.getUserPrincipal()!=null){ - + diff --git a/src/main/webapp/tools/bootstrap/css/bootstrap.css b/src/main/webapp/tools/bootstrap/css/bootstrap.css index c46af7dfbd..5690cfca7e 100755 --- a/src/main/webapp/tools/bootstrap/css/bootstrap.css +++ b/src/main/webapp/tools/bootstrap/css/bootstrap.css @@ -1389,8 +1389,8 @@ a.bg-danger:hover { } .page-header { padding-bottom: 9px; - margin: 40px 0 20px; - border-bottom: 1px solid #eee; + margin: 40px 0 10px; + /* border-bottom: 1px solid #eee; */ } ul, ol {