feat(console): integrate app (#7417)

* docs, frameworks view

* project select, integrate app page

* fix search project autocomplete

* framework autocomplete

* framwork select component, integrate, mapping to oidc config

* param

* fix route handler

* setname projectid context

* app-create page without context

* show description of app type, info section

* redirects section

* updatevalue observable

* fix redirect uris section

* i18n

* setup config

* backbutton behavior, cleanup

* cleanup

* lint

* allow other framework jump off

* dev mode warning

* navigate to project

* rm import

* i18n, guide link

* edit name dialog

* show warning for duplicate name
This commit is contained in:
Max Peintner
2024-02-28 16:52:21 +00:00
committed by GitHub
parent f4c72cbe14
commit 0fcdfe460c
64 changed files with 2381 additions and 176 deletions
@@ -0,0 +1,23 @@
<div class="quickstart-header">
<div class="quickstart-left">
<h2>{{ 'QUICKSTART.TITLE' | translate }}</h2>
<p class="description">{{ 'QUICKSTART.DESCRIPTION' | translate }}</p>
<div class="btn-wrapper">
<a mat-raised-button color="primary" [routerLink]="['/projects', 'app-create']">{{
'QUICKSTART.BTN_START' | translate
}}</a>
<a mat-stroked-button color="primary" href="https://zitadel.com/docs/sdk-examples/introduction" target="_blank">{{
'QUICKSTART.BTN_LEARNMORE' | translate
}}</a>
</div>
</div>
<div class="quickstart-card-wrapper">
<ng-container *ngFor="let framework of frameworks.slice(0, 18)">
<a [routerLink]="['/projects', 'app-create']" [queryParams]="{ framework: framework.id }" class="quickstart-card card">
<img class="dark-only" *ngIf="framework.imgSrcDark" [src]="framework.imgSrcDark" alt="{{ framework.title }}" />
<img class="light-only" *ngIf="framework.imgSrcLight" [src]="framework.imgSrcLight" alt="{{ framework.title }}" />
</a>
</ng-container>
</div>
</div>
@@ -0,0 +1,121 @@
@mixin quickstart-theme($theme) {
$primary: map-get($theme, primary);
$warn: map-get($theme, warn);
$background: map-get($theme, background);
$accent: map-get($theme, accent);
$primary-color: map-get($primary, 500);
$warn-color: map-get($warn, 500);
$accent-color: map-get($accent, 500);
$foreground: map-get($theme, foreground);
$is-dark-theme: map-get($theme, is-dark);
$back: map-get($background, background);
$list-background-color: map-get($background, 300);
$card-background-color: map-get($background, cards);
$border-color: if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
$border-selected-color: if($is-dark-theme, #fff, #000);
.quickstart-header {
display: flex;
flex-direction: row;
margin: 0 -2rem;
padding: 2rem;
margin-bottom: 2rem;
gap: 5rem;
justify-content: space-between;
background-color: map-get($background, metadata-section);
.quickstart-left {
display: flex;
flex-direction: column;
max-width: 400px;
.btn-wrapper {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 1rem;
margin: 1rem 0;
}
}
.quickstart-card-wrapper {
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-column-gap: 1rem;
grid-row-gap: 1rem;
grid-auto-columns: 0;
overflow-x: hidden;
box-sizing: border-box;
max-width: 600px;
margin-left: auto;
.quickstart-card {
position: relative;
flex-shrink: 0;
text-decoration: none;
cursor: pointer;
border-radius: 0.5rem;
box-sizing: border-box;
transition: all 0.1s ease-in;
display: flex;
flex-direction: column;
height: 60px;
width: 60px;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0 3px #0000001a;
border: 1px solid rgba(#8795a1, 0.2);
color: var(--success);
opacity: 0.8;
&:hover {
border: 2px solid var(--success);
opacity: 1;
}
img {
width: 100%;
height: 100%;
max-width: 40px;
max-height: 40px;
object-fit: contain;
object-position: center;
}
.dark-only {
display: if($is-dark-theme, block, none);
}
.light-only {
display: if($is-dark-theme, none, block);
}
span {
margin: 0.5rem;
text-align: center;
color: map-get($foreground, text);
}
.action-row {
display: flex;
align-items: center;
justify-content: flex-end;
font-size: 14px;
margin-bottom: 0.5rem;
color: map-get($primary, 400);
.icon {
margin-left: 0rem;
}
}
&:hover {
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.12);
}
}
}
}
}
@@ -0,0 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { QuickstartComponent } from './quickstart.component';
describe('QuickstartComponent', () => {
let component: QuickstartComponent;
let fixture: ComponentFixture<QuickstartComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [QuickstartComponent],
});
fixture = TestBed.createComponent(QuickstartComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,42 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { RouterModule } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
import frameworkDefinition from '../../../../../docs/frameworks.json';
import { MatButtonModule } from '@angular/material/button';
import { listFrameworks, hasFramework, getFramework } from '@netlify/framework-info';
import { FrameworkName } from '@netlify/framework-info/lib/generated/frameworkNames';
import { OIDC_CONFIGURATIONS } from 'src/app/utils/framework';
export type FrameworkDefinition = {
id?: FrameworkName | string;
title: string;
description?: string;
imgSrcDark: string;
imgSrcLight?: string;
docsLink: string;
external?: boolean;
};
export type Framework = FrameworkDefinition & {
fragment: string;
};
@Component({
standalone: true,
selector: 'cnsl-quickstart',
templateUrl: './quickstart.component.html',
styleUrls: ['./quickstart.component.scss'],
imports: [TranslateModule, RouterModule, CommonModule, MatButtonModule],
})
export class QuickstartComponent {
public frameworks: FrameworkDefinition[] = frameworkDefinition
.filter((f) => f.id && OIDC_CONFIGURATIONS[f.id])
.map((f) => {
return {
...f,
imgSrcDark: `assets${f.imgSrcDark}`,
imgSrcLight: `assets${f.imgSrcLight ? f.imgSrcLight : f.imgSrcDark}`,
};
});
}