Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions phenoxtract-ui/.postcssrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"plugins": {
"@tailwindcss/postcss": {}
}
}
4 changes: 4 additions & 0 deletions phenoxtract-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@angular/platform-browser": "^20.1.4",
"@angular/router": "^20.1.4",
"@primeuix/themes": "^2.0.3",
"@tailwindcss/postcss": "^4.3.2",
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-dialog": "^2.7.1",
"@tauri-apps/plugin-opener": "^2",
Expand All @@ -41,10 +42,13 @@
"@eslint/js": "^10.0.1",
"@tauri-apps/cli": "^2",
"angular-eslint": "^22.0.0",
"autoprefixer": "^10.5.2",
"eslint": "^10.6.0",
"eslint-config-prettier": "^10.1.8",
"jsdom": "^29.1.1",
"postcss": "^8.5.16",
"prettier": "^3.9.4",
"tailwindcss": "^4.3.2",
"typescript": "~5.8.3",
"typescript-eslint": "^8.62.1",
"vite": "^8.1.3",
Expand Down
248 changes: 237 additions & 11 deletions phenoxtract-ui/pnpm-lock.yaml

Large diffs are not rendered by default.

118 changes: 8 additions & 110 deletions phenoxtract-ui/src/app/app.component.css
Original file line number Diff line number Diff line change
@@ -1,112 +1,10 @@
.logo.angular:hover {
filter: drop-shadow(0 0 2em #e32727);
.app-container {
display: flex;
height: 100vh;
width: 100vw;
overflow: hidden;
}
:root {
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 400;

color: #0f0f0f;
background-color: #f6f6f6;

font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}

.container {
margin: 0;
padding-top: 10vh;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
}

.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: 0.75s;
}

.logo.tauri:hover {
filter: drop-shadow(0 0 2em #24c8db);
}

.row {
display: flex;
justify-content: center;
}

a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}

a:hover {
color: #535bf2;
}

h1 {
text-align: center;
}

input,
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
color: #0f0f0f;
background-color: #ffffff;
transition: border-color 0.25s;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
}

button {
cursor: pointer;
}

button:hover {
border-color: #396cd8;
}
button:active {
border-color: #396cd8;
background-color: #e8e8e8;
}

input,
button {
outline: none;
}

#greet-input {
margin-right: 5px;
}

@media (prefers-color-scheme: dark) {
:root {
color: #f6f6f6;
background-color: #2f2f2f;
}

a:hover {
color: #24c8db;
}

input,
button {
color: #ffffff;
background-color: #0f0f0f98;
}
button:active {
background-color: #0f0f0f69;
}
}
.icon-color {
color: var(--p-primary-color);
}
69 changes: 66 additions & 3 deletions phenoxtract-ui/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,66 @@
<main class="container">
<router-outlet />
</main>
<div class="app-container">
<app-sidebar>
<ng-template pTemplate="header">
<app-brand />
</ng-template>

<ng-template pTemplate="body">
<div class="flex flex-col px-4 gap-2 w-full">
<p-button class="w-full" styleClass="w-full justify-start!" label="Projects" />

<p-button
class="w-full bg-transparent!"
styleClass="w-full justify-start! bg-transparent! hover:!bg-[var(--p-primary-color)] hover:!text-[var(--p-primary-contrast-color)]"
label="Settings"
severity="secondary"
text
/>

<p-button
class="w-full"
styleClass="w-full justify-start! bg-transparent! hover:!bg-[var(--p-primary-color)] hover:!text-[var(--p-primary-contrast-color)]"
label="Documentation"
severity="secondary"
text
/>
</div>
</ng-template>

<ng-template pTemplate="footer">
<a
pButton
[rounded]="true"
[text]="true"
href="https://github.com/P2GX/PhenoXtract"
target="_blank"
rel="noopener noreferrer"
size="large"
>
<i class="bi bi-github icon-color text-3xl"></i>
</a>
<a
pButton
[rounded]="true"
[text]="true"
href="https://github.com/P2GX/PhenoXtract/issues"
target="_blank"
rel="noopener noreferrer"
size="large"
>
<i class="bi bi-bug-fill icon-color text-3xl"></i>
</a>
<a
pButton
[rounded]="true"
[text]="true"
href="mailto:Rouven.Reuter@bih-charite.de,patrick-simon.nairne@bih-charite.de"
target="_blank"
rel="noopener noreferrer"
size="large"
>
<i class="bi bi-mailbox2-flag icon-color text-3xl"></i>
</a>
</ng-template>
</app-sidebar>
</div>
<router-outlet />
6 changes: 5 additions & 1 deletion phenoxtract-ui/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { FormsModule } from '@angular/forms';

import { ButtonModule } from 'primeng/button';
import { Sidebar } from './shared/components/sidebar/sidebar.component';
import { BrandComponent } from './shared/components/brand/brand.component';

@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet, FormsModule],
imports: [RouterOutlet, FormsModule, ButtonModule, Sidebar, BrandComponent],
templateUrl: './app.component.html',
styleUrl: './app.component.css',
})
Expand Down
6 changes: 6 additions & 0 deletions phenoxtract-ui/src/app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ export const appConfig: ApplicationConfig = {
providePrimeNG({
theme: {
preset: Nora,
options: {
cssLayer: {
name: 'primeng',
order: 'theme, base, primeng',
},
},
},
}),
],
Expand Down
57 changes: 57 additions & 0 deletions phenoxtract-ui/src/app/shared/components/brand/brand.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Component, OnInit, signal } from '@angular/core';
import { invoke } from '@tauri-apps/api/core';

@Component({
selector: 'app-brand',
standalone: true,
template: `
<div class="brand-container">
<img alt="PX Logo" src="assets/icons/px-logo.png" class="logo" />
<div class="brand-text">
<h1>Phenoxtract</h1>
<span>{{ version() }}</span>
</div>
</div>
`,
styles: [
`
.brand-text h1 {
font-size: 1.35rem;
margin: 0;
font-weight: normal;
font-family: var(--highlight-font), sans-serif;
color: black;
}

.brand-text span {
font-size: 0.75rem;
color: #c1c1c1;
font-family: var(--global-font), sans-serif;
}

.logo {
height: 3.5em;
will-change: filter;
transition: 0.75s;
}

.brand-container {
display: flex;
align-items: center;
gap: 1rem;
}
`,
],
})
export class BrandComponent implements OnInit {
version = signal('');

async ngOnInit(): Promise<void> {
try {
this.version.set(await invoke<string>('get_version'));
} catch (error) {
console.error('Failed to get app version:', error);
this.version.set('Unknown');
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import {
Component,
ContentChildren,
QueryList,
TemplateRef,
AfterContentInit,
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { PrimeTemplate } from 'primeng/api';

@Component({
selector: 'app-sidebar',
standalone: true,
imports: [CommonModule],
template: `
<aside class="sidebar">
@if (headerTemplate) {
<header class="top">
<ng-container *ngTemplateOutlet="headerTemplate"></ng-container>
</header>
}

@if (bodyTemplate) {
<ng-container *ngTemplateOutlet="bodyTemplate"></ng-container>
}

@if (footerTemplate) {
<footer>
<ng-container *ngTemplateOutlet="footerTemplate"></ng-container>
</footer>
}
</aside>
`,
styles: [
`
footer {
display: flex;
padding: 1rem;
background: var(--bg-color);
margin-top: auto;
justify-content: space-evenly;
gap: 0.5rem;
}

.sidebar {
width: 250px;
border-right: 1px solid #6a7282;
display: flex;
flex-direction: column;
padding-top: 1rem;
background-color: var(--bg-color);
height: 100%;
}

.top {
display: flex;
align-items: center;
padding: 0 1.5rem 2rem 1.5rem;
gap: 0.75rem;
}
`,
],
})
export class Sidebar implements AfterContentInit {
@ContentChildren(PrimeTemplate) templates!: QueryList<PrimeTemplate>;

headerTemplate: TemplateRef<unknown> | null = null;
bodyTemplate: TemplateRef<unknown> | null = null;
footerTemplate: TemplateRef<unknown> | null = null;

ngAfterContentInit() {
this.templates.forEach((item) => {
switch (item.getType()) {
case 'header':
this.headerTemplate = item.template;
break;
case 'body':
this.bodyTemplate = item.template;
break;
case 'footer':
this.footerTemplate = item.template;
break;
}
});
}
}
Binary file added phenoxtract-ui/src/assets/icons/px-logo-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added phenoxtract-ui/src/assets/icons/px-logo-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added phenoxtract-ui/src/assets/icons/px-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading