Skip to content
Snippets Groups Projects
user avatar
Julien Touchais authored
c08d2cb8
History


snoBoard
snoBoard

A guided RNA modifications catalog.

Note: this is the repository for the web client of snoBoard.

Website GitLab License GitLab Issues

Key FeaturesCreditsDo it yourselfCode style guidelines

Key Features

  • Visualize RNA modifications data from snoBoard's database
  • Represent interaction between guide and target RNAs
  • Represent target RNAs secondary structure
  • Perform conservation analysis across species
    • Visualise sequence alignment
    • Perform bases & modifications conservation analysis on the alignment
  • Show statistics about the organisms present in the database
  • Explore snoBoard's API without leaving the website

Credits

This software uses the following open source packages:

Run locally

Setup

npm install

Create a .env file, and define the following environment variables:

Variable Description Example value
VITE_API_URL URL of the GraphQL API endpoint 'https://example.com:4000/graphql'
VITE_STATIC_URL URL where static files can be found (e.g. target secondary structure, sequences...) 'https://example.com:4000/'

Develop

npm run dev

Test

# unit testing (Vitest):
npm run test:unit

Build

npm run build

Tooling

VSCodium + Volar (not Vetur) is a recommended setup.

For support of .vue imports in TS, chose your path and follow the steps below:

1. TypeScript Vue Plugin

Pro: One-time setup
Con: Two TS language services are running in parallel (Codium's default and plugin one), which can impact Codium performances

Install the TypeScript Vue Plugin (Volar), and you're ready to go.

2. Volar "Takeover Mode" (recommended)

Pro: Only one TS language service running
Con: A quick setup is needed for each project

  1. Disable the built-in TypeScript Extension
    1. Run Extensions: Show Built-in Extensions from VSCode's command palette
    2. Find TypeScript and JavaScript Language Features, right click and select Disable (Workspace)
  2. Reload the VSCode window by running Developer: Reload Window from the command palette.

Source: https://vuejs.org/guide/typescript/overview.html#volar-takeover-mode

Code style guidelines

Project structure

The project files structure is the following:

📂 snoboard-client
├── ⚙️ package.json (& other config files)
├── 🔑 .env (& env.d.ts)
├── 📄 index.html
├── ⚖️ LICENSE
├── 📁 public
└── 📂 src
    ├── 📄 App.vue
    ├── 📄 main.ts
    ├── 📂 router
    │   └── 📄 index.ts
    ├── 📁 views
    ├── 📁 layouts
    ├── 📁 components
    ├── 📁 composables
    ├── 📁 utils
    ├── 📁 services
    ├── 📁 gql
    ├── 📁 typings
    └── 📁 assets

Description of the files & folders

⚙️ package.json & other config files

Multiple config files are present at the root of the project to configure the different tools & packages used in the application. The most noticeable one is the usual Node's package.json (along with npm's generated package-lock.json), giving the description of the project (name, version, npm scripts, dependencies).
Apart from it, we have config files for:

🔑 .env & env.d.ts

The .env file is not published in the repository and needs to be created and filled by the developer as explained above. It contains the environment variables, which are instance-specific, and works according to the Vite's environment variables specification.
The file env.d.ts defines TypeScript types which needs to be globally available, thus including the environment variables in the .env file as described in Vite's documentation.

Describing environment variables in env.d.ts won't ensure that those variables will actually be available. The types will be defined, so it won't generate type error when using them, but if the variables are not actually set in .env., it will still generate a run-time error because they won't exist.**

📄 index.html

Like in all Vite project, the index.html file is the entry point of the website, and is located at the root of the project. It will be the file served when requesting the website, and does not normally need to be modified (except e.g. when changing favicon).

📂 public

All content placed in the public folder will be available as static asset, served as-is at the root path (/). This is for example appropriate for the website's favicon.

📂 src

The src folder contains files which will be processed when building the application. Those files are separated in different folder according to their role — except for App.vue & main.ts.

An alias defined in Vite configuration allows to use @ in paths to reference this folder.

📄 App.vue & main.ts

The main.ts file is embedded in index.html. It will thus be the first loaded, and is responsible for importing global assets (like CSS stylesheets), and mainly for creating the Vue application and configuring it (applying plugins, registering global components, creating directives, ...), and then mounting it in index.html.
The App.vue file is the root component and the entry point of the Vue application, used by main.ts to create the app with. Each page of the website will actually display it, and it will be in charge to load a different content given the requested page (using the router, described below).

📄 router/index.ts

This file contains the configuration of the router, which is responsible for displaying the page matching the requested URL (this redirection mechanism is called routing, with each accessible location being a route, defined in this file). It exports a router instance, imported in main.ts and applied as a plugin of the Vue application.
The routing is then put in practice using RouterView & RouterLink components, especially in App.vue which is basically only a RouterView.

📂 views

As the name suggests, this folder contains the views of the application, which are meta-components representing a page of the website each. Those components are used in the router configuration, a view being attributed to each route, and so displayed by the RouterView in App.vue.

📂 layouts

This folder contains components which are meant to be used as layout for the pages, encapsulating their content. They are usually used at the top-level of a view, and all the view content is placed inside the layout component using a slot. An layout example is the main one (MainLayout.vue), which consists in the header bar and the footer (which by the way is itself a layout), and is used in almost every view.

📂 components

All the remaining components of the application are placed in this folder.

📂 composables

This folder contains the composables of the application, which are utilities using the Vue's Composition API & reactivity system to provide a stateful logic (i.e. which depends on the current state of the application).

📂 utils

This folder contains all stateless utilities (i.e. not composables), functions, constants which we don't want to define directly in the components (because reused, too large or another good reason).

📂 services

This folder contains the configuration of services used by the application, which are then used in main.ts in application configuration. For now, this only concern the configuration of the urql client.

📂 gql

This folder contains all which is related to the GraphQL API (except the configuration of the client which is done in 📂 services). Its structure is the following:

TBD

TBD

📂 typings

This folder contains all the TypeScript types & interfaces which are either not specially linked to a component (so can't be defined in it), to large to fit in, or any good reason.

📂 assets

This folder contains all the assets of the application (CSS stylesheets, images, icons). Its structure is the following:

TBD

TBD usage

Naming conventions

  • Base components, i.e. components which does not store application state should start with "Base" prefix (see corresponding Vue.js style guide)
  • Views:
    • Component which are views (in the views folder) should end with
  • Composables:
    • Compos

Imports organisation in JS/TS

JS or TS code files - including the <script> part of Vue's SFCs, should be organised in the following way for how they import other code, which should be done at the top of the file:

/**
 * Vue imports
 */
import { ... } from 'vue'
import { ... } from 'vue-router' // Place official Vue ecosystem libs here too.
/**
 * Components imports
 */
import ... from 'componentLib/some3PComponent'
import ... from '@/components/someLocalComponent'
import ... from '@/layout/someLayoutComponent'
import ... from '@/views/someViewComponent'
/**
 * Composables imports
 */
import ... from '@/composables/useSomeComposable'
import { ... } from '@vueuse/core'
/**
 * Other 3rd-party imports
 */
import { ... } from 'lodash-es'
/**
 * Stores imports
 */
import { ... } from '@/stores/someStore'
/**
 * Types imports
 */
import { type ... } from 'lib/someTypes'
import { type ... } from '@/typings/someTypes'
/**
 * Utils imports
 */
import { ... } from '@/utils/someUtil'
/**
 * Assets imports
 */
import ... from '@/assets/path/to/asset'

Tailwind classes with Vue

Vue has several ways to define classes, including an object syntax and an array syntax. To deal with Tailwind's classes in a consistent way, the following guidelines should be observed:

  • Write predetermined classes inline:
    class="class-1 class-2..."
  • Write parametrised classes as template literals:
    :class="`class-${param} class-${param2}`"
  • Write conditioned classes with object syntax if there is only one class for each condition, otherwise use ternary or &&:
    :class="{
      'class-1': condition1,
      // to use template literal as key, enclose it in brackets:
      [`class-${two}`]: condition2
    }"
    // if more than 1 class/condition:
    :class="condition ? 'class-1' : 'class-2 class-3'"
    :class="condition && 'class-1 class-2 class-3'"
  • Finally, if several of these forms have to be used, combine them with the array syntax:
    :class="[
      `class-${param}`,
      {
        'class-2': condition
      },
      condition2 && 'class-3',
      'class-4 class-5'
    ]"

These rules can be applied in kind of a recursive manner, for example when using parametrised class in a conditional one.