diff --git a/src/components/LandingBackground/landingBackground.js b/src/components/LandingBackground/landingBackground.js index 29e4765..4320255 100644 --- a/src/components/LandingBackground/landingBackground.js +++ b/src/components/LandingBackground/landingBackground.js @@ -1,15 +1,17 @@ -import React, { useEffect, useState } from 'react'; -import { Canvas } from '@react-three/fiber'; +import React, { useEffect, useState, useRef } from 'react'; +import { Canvas, extend} from '@react-three/fiber'; +import { WebGLRenderer } from 'three'; import Scene from './scene'; const LandingBackground = () => { const [contextLost, setContextLost] = useState(false); const [webGLSupported, setWebGLSupported] = useState(true); + const canvasRef = useRef(); useEffect(() => { const canvasElem = document.createElement('canvas'); const gl = canvasElem.getContext('webgl') || canvasElem.getContext('experimental-webgl'); - + if (!gl) { setWebGLSupported(false); console.log('WebGL is not supported by your browser or device.'); @@ -23,20 +25,25 @@ const LandingBackground = () => { const handleContextLost = (event) => { event.preventDefault(); setContextLost(true); - console.log("WebGL context lost. Please refresh the page or try with a different browser/device."); + console.log("WebGL context lost. Attempting to restore..."); }; const handleContextRestored = () => { setContextLost(false); - console.log("WebGL context restored. Reinitializing component..."); + console.log("WebGL context restored. Reinitializing renderer..."); + // Reinitialize the renderer here + if (canvasRef.current) { + const renderer = new WebGLRenderer({ canvas: canvasRef.current }); + extend({ renderer }); + } }; - document.addEventListener('webglcontextlost', handleContextLost); - document.addEventListener('webglcontextrestored', handleContextRestored); + canvasElem.addEventListener('webglcontextlost', handleContextLost); + canvasElem.addEventListener('webglcontextrestored', handleContextRestored); return () => { - document.removeEventListener('webglcontextlost', handleContextLost); - document.removeEventListener('webglcontextrestored', handleContextRestored); + canvasElem.removeEventListener('webglcontextlost', handleContextLost); + canvasElem.removeEventListener('webglcontextrestored', handleContextRestored); }; }, []); @@ -46,8 +53,8 @@ const LandingBackground = () => { return ( contextLost ? -
WebGL context lost. Please refresh the page or try with a different browser/device.
: - +
WebGL context lost. Attempting to restore...
: + diff --git a/src/components/LandingDownloadLink/landingDownloadLink.js b/src/components/LandingDownloadLink/landingDownloadLink.js index f7e6868..8dc391f 100644 --- a/src/components/LandingDownloadLink/landingDownloadLink.js +++ b/src/components/LandingDownloadLink/landingDownloadLink.js @@ -1,10 +1,11 @@ import React from 'react'; +import LandingDownloadLinkStyles from './landingDownloadLink.module.css' const LandingDownloadLink = ({ fileName, label }) => { const fileUrl = `${process.env.PUBLIC_URL}/useCases/${fileName}`; return ( - + {label} ); diff --git a/src/components/LandingDownloadLink/landingDownloadLink.module.css b/src/components/LandingDownloadLink/landingDownloadLink.module.css new file mode 100644 index 0000000..74d5c5c --- /dev/null +++ b/src/components/LandingDownloadLink/landingDownloadLink.module.css @@ -0,0 +1,31 @@ +.linkElement { + cursor: pointer; + transition: background-color 0.3s ease, box-shadow 0.3s ease, transform 0.2s ease; + background-color: #3d3d3d; + color: #ffffff; + padding: 12px 24px; + border-radius: 4px; + border: 2px solid transparent; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2); + font-weight: 600; + font-size: 1.1rem; + text-align: center; + display: inline-flex; + align-items: center; + justify-content: center; + text-transform: uppercase; + letter-spacing: 1.2px; + text-decoration: none; +} + +.linkElement:hover, .linkElement:focus { + background-color: #333333; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3); + transform: translateY(-2px); +} + +.linkElement:active { + background-color: #0d0d0d; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25); + transform: translateY(1px); +} diff --git a/src/components/LandingImage/landingImage.js b/src/components/LandingImage/landingImage.js index 4f8ba9c..30965b9 100644 --- a/src/components/LandingImage/landingImage.js +++ b/src/components/LandingImage/landingImage.js @@ -1,7 +1,7 @@ import React, { useEffect, useRef, useState } from "react"; import LandingImageStyles from "./landingImage.module.css"; -const LandingImage = ({ imageSrc, width, height, maintainAspectRatio = false }) => { +const LandingImage = ({ imageSrc, width, height, maintainAspectRatio = false, addDarkBorder = false }) => { const [animationOffset, setAnimationOffset] = useState(1); const imageRef = useRef(null); @@ -29,8 +29,13 @@ const LandingImage = ({ imageSrc, width, height, maintainAspectRatio = false }) ? { maxWidth: '100%', maxHeight: '100%' } : { width: width, height: height }; + let imageContainerClass = LandingImageStyles.image; + if (addDarkBorder) { + imageContainerClass += ` ${LandingImageStyles.darkShadow}`; + } + return ( -
+
Sample
); diff --git a/src/components/LandingImage/landingImage.module.css b/src/components/LandingImage/landingImage.module.css index 0e082fd..550713d 100644 --- a/src/components/LandingImage/landingImage.module.css +++ b/src/components/LandingImage/landingImage.module.css @@ -1,4 +1,5 @@ .image { + position: relative; display: flex; justify-content: center; align-items: center; @@ -9,4 +10,16 @@ .image img { max-width: 100%; max-height: 100%; + display: block; +} + +.darkShadow::after { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + box-shadow: 0 0 0 2px #000000; + pointer-events: none; } diff --git a/src/components/LandingSlide/landingSlide.module.css b/src/components/LandingSlide/landingSlide.module.css index 1f043d0..49ec4cc 100644 --- a/src/components/LandingSlide/landingSlide.module.css +++ b/src/components/LandingSlide/landingSlide.module.css @@ -3,8 +3,10 @@ width: 100%; max-width: 800px; margin: auto; - border: 2px solid #ddd; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + border: 2px solid #ddd; /* Consider adding a gradient or a more appealing solid color */ + border-radius: 10px; /* Rounded corners */ + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); /* More refined shadow */ + overflow: hidden; /* To ensure rounded corners are applied to child elements */ } .imageContainer { @@ -18,9 +20,12 @@ top: 0; left: 50%; transform: translateX(-50%); - max-width: 100%; - max-height: 100%; - object-fit: contain; + width: 100%; + /* Adjusted to ensure full width */ + height: 100%; + /* Adjusted to ensure full height */ + object-fit: cover; + /* Changed from 'contain' to 'cover' */ opacity: 0; transition: opacity 1s ease-in-out; } @@ -29,36 +34,25 @@ opacity: 1; } - .slideTextContainer { margin-top: 20px; text-align: center; padding: 15px 20px; color: #333; background-color: #ffffff; - /* Lighter background for better readability */ border: 1px solid #ccc; - /* Softer border color */ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - /* Slightly larger shadow for depth */ border-radius: 8px; - /* Increased border-radius for a modern look */ max-width: 90%; - /* Limiting the maximum width for better text display */ margin-left: auto; - /* Center align the container */ margin-right: auto; } .slideText { font-size: 18px; - /* Increased font size */ line-height: 1.6; - /* Improved line height for readability */ color: #555; - /* Slightly darker color for contrast */ font-weight: 400; - /* Normal font-weight for better readability */ } .controls { diff --git a/src/components/Navbar/navbar.js b/src/components/Navbar/navbar.js index 523c789..e5c67a4 100644 --- a/src/components/Navbar/navbar.js +++ b/src/components/Navbar/navbar.js @@ -23,7 +23,7 @@ export default function Navbar() { Home
  • - Queries + Queries
  • About diff --git a/src/components/ResultTray/resultTray.js b/src/components/ResultTray/resultTray.js index dbd6317..659f3ac 100644 --- a/src/components/ResultTray/resultTray.js +++ b/src/components/ResultTray/resultTray.js @@ -131,7 +131,7 @@ function ResultTray({ activeGraphId, graphs, allNodes, edgeData, insideData, bin shownOptionals = []; } else { - buttonPropertyLabel = `Set '${selectedNode.type}' properties`; + buttonPropertyLabel = `Set '${selectedNode.type}' object properties`; buttonOptionalLabel = `Set '${selectedNode.type}' optional properties`; buttonInsideLabel = `Set '${selectedNode.type}' data properties`; diff --git a/src/components/SearchResults/searchResults.module.css b/src/components/SearchResults/searchResults.module.css index 10c80a9..e93dd27 100644 --- a/src/components/SearchResults/searchResults.module.css +++ b/src/components/SearchResults/searchResults.module.css @@ -37,8 +37,8 @@ .resultCount { display: none; position: absolute; - bottom: 0px; - right: 0px; + bottom: 0; + right: 0; background-color: lightGray; padding: 2px; border-radius: 2px; @@ -47,7 +47,7 @@ } .resultCount.shown { - display: inline; + display:inline-block; } .openButton { @@ -84,9 +84,10 @@ .input::-webkit-search-cancel-button { display: none; } - +/* @-moz-document url-prefix() { .resultCount { bottom: calc(-980%); } -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/src/index.js b/src/index.js index 01502e5..20e1531 100644 --- a/src/index.js +++ b/src/index.js @@ -25,7 +25,7 @@ root.render( element={
    } > } > { const importImages = async () => { const imageArray = []; - for (let i = 1; i <= 9; i++) { - const image = await import(`../resources/images/tutorial/Figure${i}.png`); - imageArray.push(image.default); + for (let i = 1; i <= 11; i++) { + if (i === 6) { + const geneImage = await import(`../resources/images/tutorial/geneProps.png`); + imageArray.push(geneImage.default); + } else if (i === 7) { + const protImage = await import(`../resources/images/tutorial/protProps.png`); + imageArray.push(protImage.default); + } else { + const image = await import(`../resources/images/tutorial/Figure${i}.png`); + imageArray.push(image.default); + } } setImages(imageArray); } importImages(); }, []); + useEffect(() => { const slideImages = []; for (let i = 1; i <= 7; i++) { @@ -101,14 +110,29 @@ function Main() { const tutorialSteps = [ 'No need to know querying languages to explore the RDF.', - 'Select the first node or subject, in this case, Gene, in the variables section.', - 'Select the second node or object, in this case, Protein, in the variables section.', - 'Select the object property that relates both entities, in this case, "encodes".', - 'Select in "Nodes shown" the data we want to show in the output.', + 'Select the first node or subject, in this case, Gene, in the Variable browser.', + 'Select the second node or object, in this case, Protein, in the Variable browser.', + 'Select in the Properties selectors the one that relates both, in this case, "encodes".', + 'Select in "Nodes shown" in the Query builder the data we want to show in the output.', 'Click on "Query" to launch the query.', 'Click on "Export as" to download the data. Click on "Export query" to save the query.' ]; + function OverlappingImages({ images }) { + return ( +
    + {images.map((image, index) => ( + {image.alt} + ))} +
    + ); + } + return (
    @@ -118,12 +142,12 @@ function Main() {
    -

    Introduction

    +

    Introduction

    INTUITION is a web application for user-friendly SPARQL query building. It analyses an accessible endpoint, BioGateway, and allows building queries graphically by representing nodes (entities) and edges (properties).

    - RDF knowledge graphs represent entities through uniform resource identifiers (URIs), and information through triples or statements that represent a directional relationship between two entities, similar to a sentence: {"<"}subject{">"} {"<"}predicate{">"} {"<"}object{">"}. For example: {"<"}Gene{">"} {"<"}encodes{">"} {"<"}Protein{">"}. The SPARQL query language also uses this pattern to build queries. These queries can be complex by linking multiple triples and including operations. A tutorial for building SPARQL queries in BioGateway (BGW) is available in this repository (https://github.com/juan-mulero/cisreg). + RDF knowledge graphs represent entities through uniform resource identifiers (URIs), and information through triples or statements that represent a directional relationship between two entities, similar to a sentence: {"<"}subject{">"} {"<"}predicate{">"} {"<"}object{">"}. For example: {"<"}Gene{">"} {"<"}encodes{">"} {"<"}Protein{">"}. The SPARQL query language also uses this pattern to build queries. These queries can be complex by linking multiple triples and including operations. A tutorial for building SPARQL queries in BioGateway (BGW) is available in this repository.
    @@ -132,13 +156,13 @@ function Main() {
    -

    Design

    +

    Design

    The INTUITION interface is composed of the following sections:
    - {images[0] && } + {images[0] && }
    -

    Query building made easy

    +

    Query building made easy

    @@ -218,12 +242,23 @@ function Main() {
    -

    Filters and Other Clauses

    +

    Filters and Other Clauses

    - INTUITION offers various clauses like DISTINCT, COUNT, VALUES, and filters to refine your queries. You can easily apply these clauses and filters through the interface to achieve more precise results. - {images[4] && } - {images[5] && } - {images[6] && } + Each entity's attributes can also be filtered through the 'Data properties' modal, in the Property Selector. + +
    + +
    + + INTUITION offers various clauses like DISTINCT and COUNT to refine your queries. You can easily apply these clauses and filters through the interface to achieve more precise results. + + {images[4] && } +
    + {/* Load Values.png before the VALUES text */} + +
    + + In the Property Selector, VALUES statements can be defined introducing each element of the value pile. The input values for filtering must be URIs.
    @@ -232,40 +267,86 @@ function Main() {
    -

    Creating and Filtering Variables

    +

    Creating and Filtering Variables

    INTUITION supports the generation and filtering of new variables. This functionality is implemented in "Nodes shown" {">"} "Bindings" button. For example, by subtracting the end and start positions of the CRMs we obtain the length of the sequences in a new variable. Then, we can filter this new variable in the “Filters set” button. - {images[7] && } + {images[7] && } + {images[8] && } + {images[9] && }
    {/* UNION Clause Section */}
    -
    -
    -

    UNION Clause

    - - INTUITION also allows the use of the UNION clause of SPARQL. UNION merges subqueries through common variables in both queries. We illustrate its use through a use case. For example, we retrieve the OMIM entities that contain the string "breast cancer" as a name or synonym. To do that, follow the steps outlined in the tutorial. - {images[8] && } - +

    UNION Clause

    + + INTUITION also allows the use of the UNION clause. UNION merges subqueries through common variables in both queries. We illustrate its use through a use case. For example, we retrieve the OMIM entities that contain the string "breast cancer" as a name or synonym. To do that, follow the steps outlined below: + +
    +
    + {images[10] && } +
    +
    +
      +
    1. We first create a new graph for each UNION block and add the relevant elements, in our case, OMIM.
    2. +
    3. We then configure the OMIM element in the first graph to display a property as it's 'label'.
    4. +
    5. We then do the same but for the OMIM in the other graph selecting a different property.
    6. +
    7. In the first graph we add each of the created blocks as a node...
    8. +
    9. ...And join them together using the special property 'UNION'.
    10. +
    11. From this point, we can use the configured 'label' to define filters.
    12. +
    13. Selecting OMIM as an output yields the expected results.
    14. +
    +
    +

    Variables

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    CRM variablecis regulatory module.
    Gene variablegenes.
    Protein variableproteins.
    OMIM variableentities from OMIM ontology (mainly phenotypes).
    Molecular_interactionentities from Molecular Interactions ontology (MI).
    crm2gene variablerelation between CRM and gene.
    gene2phen variablerelation between gene and phenotype.
    crm2phen variablerelation between CRM and phenotype.
    crm2tfac variablerelation between CRM and protein (transcription factor).
    Transcription factor variabletranscription factors (currently only proteins that interact with CRM).
    reg2targ variableregulatory relation between proteins.
    prot2protmolecular interaction relation between proteins.
    tfac2gene variablerelation between gene and protein.
    Database variabledatabases.
    Chromosome variablechromosomes.
    Reference_genome variablegenome assembly.
    TAD variabletopologically associated domain.
    Cellular_component variablecellular components from Gene Ontology (GO).
    prot2cc variablerelation between protein and its cellular components.
    Molecular_function variablemolecular functions from GO.
    prot2mfrelation between protein and its molecular functions.
    Biological_process variablebiological processes from GO.
    prot2bp variablerelation between protein and its biological processes.
    Ortho variableorthology relation between proteins.
    Root variabletop hierarchically class of NCBITaxon Ontology.
    Taxonomic_rank variabletop hierarchically class of NCBITaxon Ontology.
    +

    + The properties are detailed with examples and their domains here. +

    +
    {/* Use Cases Section */}
    -

    Use Cases

    +

    Use Cases

    The following Use Cases were developed in the paper "Analysis of the landscape of human enhancer sequences in biological databases". The corresponding queries are attached for reproducibility and as examples of use.
      -
    • - Use case 1:
    • -
    • - Use case 2:
    • -
    • - Use case 3:
    • + + +
    @@ -273,7 +354,7 @@ function Main() {
    {/* Get Started Button */}
    - +
    diff --git a/src/pages/main.module.css b/src/pages/main.module.css index 6cd93f1..4709f6a 100644 --- a/src/pages/main.module.css +++ b/src/pages/main.module.css @@ -24,7 +24,7 @@ padding: 20px; color: black; font-size: 35px; - text-align: center; + text-align: justify; } .contentContainer { @@ -39,20 +39,29 @@ .textImageContainer { display: flex; + flex-direction: row; align-items: center; + justify-content: space-between; margin-bottom: 20px; width: 100%; } +.textContainer, +.overlappingImagesContainer { + flex: 1; + margin: 0 10px; +} + .textContainer { flex: 1; - text-align: center; + text-align: justify; } .introText { font-size: 24px; line-height: 1.5; color: #333; + margin-bottom: 1em; } .lesserText { @@ -70,7 +79,10 @@ .imageWrapper img { width: 100%; height: auto; +} +.darkBorderImage { + border: 3px solid #000000; } .buttonContainer { @@ -148,13 +160,14 @@ justify-content: space-between; margin-top: 10px; } + .linkListItem { cursor: pointer; transition: background-color 0.3s ease, box-shadow 0.3s ease; - background-color: #f8f8f8; /* Light gray background */ + background-color: #f8f8f8; padding: 10px 15px; border-radius: 5px; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); /* Subtle shadow for depth */ + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); flex: 1; text-align: center; margin: 0 5px; @@ -163,9 +176,13 @@ justify-content: center; } +.centeredHeading { + text-align: center; +} + .linkListItem:hover { - background-color: #e9e9e9; /* Slightly darker on hover */ - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); /* More pronounced shadow on hover */ + background-color: #e9e9e9; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); } .linkItem { @@ -174,17 +191,36 @@ cursor: pointer; transition: color 0.3s ease; font-weight: bold; - display: block; /* Makes the entire area clickable */ + display: block; +} + +.linkListItem:hover .linkItem1 { + color: #ff6347; +} + +.linkListItem:hover .linkItem2 { + color: #4682b4; } -/* Color scheme based on the hover state */ -.linkListItem:hover .linkItem1 { color: #ff6347; } /* Tomato */ -.linkListItem:hover .linkItem2 { color: #4682b4; } /* SteelBlue */ -.linkListItem:hover .linkItem3 { color: #32cd32; } /* LimeGreen */ -.linkListItem:hover .linkItem4 { color: #ffa500; } /* Orange */ -.linkListItem:hover .linkItem5 { color: #6a5acd; } /* SlateBlue */ -.linkListItem:hover .linkItem6 { color: #ff1493; } /* DeepPink */ -.linkListItem:hover .linkItem7 { color: #00ced1; } /* DarkTurquoise */ +.linkListItem:hover .linkItem3 { + color: #32cd32; +} + +.linkListItem:hover .linkItem4 { + color: #ffa500; +} + +.linkListItem:hover .linkItem5 { + color: #6a5acd; +} + +.linkListItem:hover .linkItem6 { + color: #ff1493; +} + +.linkListItem:hover .linkItem7 { + color: #00ced1; +} .hoverSquare { position: absolute; @@ -196,7 +232,114 @@ visibility: visible; } +.overlappingImagesContainer { + position: relative; + justify-content: center; + align-items: center; + width: 30vh; + height: 30vh; +} + +.overlappingImage { + position: absolute; + width: 80%; + height: auto; + top: 0; + left: 0; + transition: all 0.3s ease; +} + +.image1 { + z-index: 1; + box-shadow: 0 0 0 2px #000000; +} + +.image2 { + top: -20%; + left: 10%; + z-index: 0; + box-shadow: 0 0 0 2px #000000; +} + +.variablesTable { + width: 100%; + border-collapse: collapse; + margin: 20px 0; +} + +.variablesTable th, +.variablesTable td { + border: 1px solid #8c8c8c; + padding: 8px; + text-align: left; +} + +.variablesTable th { + background-color: #f2f2f2; + color: black; +} + +.textImageContainerUnion { + display: flex; + flex-direction: row-reverse; + align-items: flex-start; + justify-content: center; + margin-bottom: 20px; + width: 100%; +} + +.imageContainerUnion { + flex: 3; + margin: 0 10px; + max-width: 75%; +} + +.textContainerUnion { + flex: 1; + text-align: left; + margin: 0 10px; + padding: 10px; + background-color: #f8f8f8; + border-radius: 10px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); +} + +.imageContainerUnion img { + width: 100%; + height: auto; +} + +.unionSteps { + list-style-type: decimal; + margin-left: 20px; + padding: 10px; + font-size: 14px; + line-height: 1.6; +} + +.unionSteps li { + margin-bottom: 10px; +} + @media (max-width: 768px) { + .textImageContainerUnion { + flex-direction: column; + } + + .imageContainerUnion, + .textContainerUnion { + width: 100%; + max-width: none; + } + + .imageContainerUnion { + order: -1; + } + + .textContainerUnion { + font-size: 16px; + } + .contentContainer { padding: 10px; } @@ -222,4 +365,9 @@ .linkListItem { margin: 5px 0; } + + .overlappingImagesContainer { + width: 80vw; + height: 80vw; + } } diff --git a/src/resources/images/tutorial/Figure10.png b/src/resources/images/tutorial/Figure10.png new file mode 100644 index 0000000..f51eace Binary files /dev/null and b/src/resources/images/tutorial/Figure10.png differ diff --git a/src/resources/images/tutorial/Figure11.png b/src/resources/images/tutorial/Figure11.png new file mode 100644 index 0000000..b5d72e4 Binary files /dev/null and b/src/resources/images/tutorial/Figure11.png differ diff --git a/src/resources/images/tutorial/Figure7.png b/src/resources/images/tutorial/Figure7.png index 2c4218f..536b89d 100644 Binary files a/src/resources/images/tutorial/Figure7.png and b/src/resources/images/tutorial/Figure7.png differ diff --git a/src/resources/images/tutorial/Figure8-removebg-preview.png:Zone.Identifier b/src/resources/images/tutorial/Figure8-removebg-preview.png:Zone.Identifier new file mode 100644 index 0000000..053d112 --- /dev/null +++ b/src/resources/images/tutorial/Figure8-removebg-preview.png:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +HostUrl=about:internet diff --git a/src/resources/images/tutorial/Figure8.png b/src/resources/images/tutorial/Figure8.png index 66decca..3a7ff0a 100644 Binary files a/src/resources/images/tutorial/Figure8.png and b/src/resources/images/tutorial/Figure8.png differ diff --git a/src/resources/images/tutorial/Figure9.png b/src/resources/images/tutorial/Figure9.png index 0d8d34b..79b5397 100644 Binary files a/src/resources/images/tutorial/Figure9.png and b/src/resources/images/tutorial/Figure9.png differ diff --git a/src/resources/images/tutorial/Values.png b/src/resources/images/tutorial/Values.png new file mode 100644 index 0000000..8b04d0a Binary files /dev/null and b/src/resources/images/tutorial/Values.png differ diff --git a/src/resources/images/tutorial/geneProps.png b/src/resources/images/tutorial/geneProps.png new file mode 100644 index 0000000..8161413 Binary files /dev/null and b/src/resources/images/tutorial/geneProps.png differ diff --git a/src/resources/images/tutorial/protProps.png b/src/resources/images/tutorial/protProps.png new file mode 100644 index 0000000..f040fbc Binary files /dev/null and b/src/resources/images/tutorial/protProps.png differ diff --git a/src/resources/images/tutorial/union(1).png:Zone.Identifier b/src/resources/images/tutorial/union(1).png:Zone.Identifier new file mode 100644 index 0000000..053d112 --- /dev/null +++ b/src/resources/images/tutorial/union(1).png:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +HostUrl=about:internet