Header Ads Widget

Ticker

6/recent/ticker-posts

Creación de la interfaz de un CMS sin cabeza en 10 pasos


 

¿Qué es Angular y por qué lo usamos?

Angular es una tecnología de interfaz de código abierto basada en mecanografiado desarrollada por Google. Se puede decir que es una versión mejorada de AngularJS ya que también está desarrollada por el mismo equipo de desarrolladores. Estamos usando Angular aquí porque es uno de los frameworks JS más populares para el desarrollo de frontend, y también es fácil de aprender si conoce los conceptos básicos de JavaScript.

Requisitos previos:

  • HTML
  • CSS
  • Angular
  • NPM
  • NodeJS
  • Cuenta Imgur con acceso a API

Paso –1: Configuración

Si no tiene un npmNodeJS, puede descargarlo desde aquí . Es una instalación sencilla.

Antes de comenzar a codificar, ya hemos creado el esqueleto de las carpetas y archivos que necesitará el proyecto. Puede instalar estas carpetas, archivos y dependencias clonándolas desde Git y ejecutando un comando simple.

Así que abre tu terminal y escribe:

git clone https://github.com/vyomsrivastava/cms-starter.git

Y entonces:

cd cms-starter

Con todas las dependencias instaladas, todo ya está configurado en el archivo package.jsonPara demostrarlo, aquí está el contenido del archivo JSON:

{
"name": "headless-cms-frontend", "version": "1.0.0", "scripts": { "ng": "ng", "start": "ng serve", "build": "ng build", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" }, "private": true, "dependencies": { "@angular/animations": "~8.0.1", "@angular/cdk": "~8.2.3", "@angular/common": "~8.0.1", "@angular/compiler": "~8.0.1", "@angular/core": "~8.0.1", "@angular/forms": "~8.0.1", "@angular/material": "^8.2.3", "@angular/platform-browser": "~8.0.1", "@angular/platform-browser-dynamic": "~8.0.1", "@angular/router": "~8.0.1", "rxjs": "~6.4.0", "tslib": "^1.9.0", "zone.js": "~0.9.1" }, "devDependencies": { "@angular-devkit/build-angular": "~0.800.0", "@angular/cli": "~8.0.4", "@angular/compiler-cli": "~8.0.1", "@angular/language-service": "~8.0.1", "@types/node": "~8.9.4", "@types/jasmine": "~3.3.8", "@types/jasminewd2": "~2.0.3", "codelyzer": "^5.0.0", "jasmine-core": "~3.4.0", "jasmine-spec-reporter": "~4.2.1", "karma": "~4.1.0", "karma-chrome-launcher": "~2.2.0", "karma-coverage-istanbul-reporter": "~2.0.1", "karma-jasmine": "~2.0.1", "karma-jasmine-html-reporter": "^1.4.0", "protractor": "~5.4.0", "ts-node": "~7.0.0", "tslint": "~5.15.0", "typescript": "~3.4.3" } }

Explicación:

Aquí enumeramos nuestros paquetes que son requeridos por la interfaz Angular. Tenemos dependencias como animationformsrouter, y otros para una animación de carga, creando formas, llamando a las API, etc.

Ahora ejecute el siguiente comando para instalarlos:

npm install

Una vez que todo esté configurado, estará listo para sumergirse en el código.

Paso –2: Configuración de la IU de administrador:

En el paso anterior, ya hemos clonado e instalado las dependencias. Ahora, tendremos que crear una interfaz de usuario para permitir que un administrador cree, edite, publique y elimine publicaciones de blog.

En su editor de código, abra el archivo admin/admin.component.tsy pegue el siguiente código:

import { AuthService } from './../auth.service';
import { DialogBodyComponent } from './../dialog-body/dialog-body.component';
import { MatDialog } from '@angular/material/dialog';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-admin',
  templateUrl: './admin.component.html',
  styleUrls: ['./admin.component.css']
})
export class AdminComponent implements OnInit {

  constructor(private dialog:MatDialog,private auth_service:AuthService) { }

  ngOnInit() {
  }

  open_dialog(message:string){
    const dialogRef = this.dialog.open(DialogBodyComponent,{
      data:{
        message
      },
      width:'550px',
      height:'200px'
    });
    dialogRef.afterClosed().subscribe((confirm:boolean)=>{
      if(confirm){
        this.sign_out();
      }
    })
  }

  sign_out(){
    this.auth_service.logout();
  }

}

Explicación:

Aquí hemos creado dos funciones open_dialoguesign_outEl open_dialoguedevolverá un cuadro de diálogo cuando se hace clic en el botón SignOut. Este es un cuadro de alerta que verá el administrador al hacer clic en Cerrar sesión.

A continuación, tenemos que trabajar en la interfaz de usuario desde donde el administrador puede publicar publicaciones de blog. Tenemos que instalar un paquete más para un editor WSYWIG.

En su terminal, pegue el siguiente comando:

npm install @syncfusion/ej2-angular-richtexteditor --save

Esto instalará un editor de texto enriquecido que proporciona muchas funcionalidades para formatear el texto, como insertar imágenes entre los párrafos y agregar fragmentos de código. Este paquete los convertirá en etiquetas HTML.

Ahora también tenemos que importar este editor en nuestro código para implementarlo también en la interfaz de usuario. Así que abre app.module.tsen el editor y pega el siguiente código:

import { RichTextEditorAllModule } from '@syncfusion/ej2-angular-richtexteditor';

Una vez hecho lo anterior, también tenemos que incluir el editor en el index.htmlarchivo. Así que abre el index.htmlarchivo y pega el siguiente código:

<link href="https://cdn.syncfusion.com/ej2/material.css" rel="stylesheet" />

Para que el editor de texto sea reutilizable, podemos convertirlo en un componente para que podamos usarlo en cualquier lugar que queramos. Así que abre admin/add-blog/add-blog.component.htmlen el editor de código y pega el siguiente código:

<div class="add-blog-input-content">
<ejs-richtexteditor [(value)]="content" height="auto" placeholder="Add Paragraph..."></ejs-richtexteditor> </div>

Paso –3: Configuración de la API de Imgur:

Usaremos Imgur para subir nuestras imágenes. Vaya a Imgur.com , cree su cuenta y obtenga sus credenciales de API . Asegúrese de seleccionar OAuth2 sin una URL de devolución de llamada.

Ahora, copie su CLIENT_ID de Imgur, abra api-calls/feature-image.service.tsy pegue el siguiente código:

import { HttpClient,HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class FeatureImageService {
  private imgur_url:string = 'https://api.imgur.com/3/image';
  private client_id:string = 'YOUR_CLIENT_ID';
  constructor(private http:HttpClient) { }

  upload_image(image_file:File){
    let formData = new FormData();
    formData.append('image',image_file, image_file.name);


    let headers = new HttpHeaders({
      "authorization": 'Client-ID '+this.client_id
    });

    return this.http.post(this.imgur_url , formData, {headers:headers});
  }
}

Pega tu CLIENT_IDen el código anterior.

Explicación:

Hemos creado una función aquí para aceptar el archivo de imagen y subirlo al servidor Imgur usando la API.

Paso –4: agregar componentes de blog

Ahora, una vez que las API de Imgur están listas, podemos crear diferentes componentes y abrirlos admin/add-blog/add-blog.component.tsen el editor de código y pegar el siguiente código:

import { AlertDialogBodyComponent } from './../../alert-dialog-body/alert-dialog-body.component';
import { BlogService } from './../../api-calls/blog.service';
import { FeatureImageService } from './../../api-calls/feature-image.service';
import { TagComponent } from './../../material-components/tag/tag.component';
import { Component, OnInit,ViewChild } from '@angular/core';
import {MatDialog} from '@angular/material/dialog';
import { DialogBodyComponent } from 'src/app/dialog-body/dialog-body.component';

@Component({
  selector: 'app-add-blog',
  templateUrl: './add-blog.component.html',
  styleUrls: ['./add-blog.component.css']
})
export class AddBlogComponent implements OnInit {
  private selectedFile:File;
  private preview_image:any;
  private tags: [];
  private title:string;
  private content:string;
  private blog_id:string;
  private show_spinner: boolean = false;
  @ViewChild(TagComponent, {static:false}) childReference:any;
  constructor(private image_service: FeatureImageService, private blog_service:BlogService, private dialog:MatDialog) { }

  ngOnInit() {
  }

  ngAfterViewInit(){
    this.tags = this.childReference.tags;
  }

  

  processFile(imageInput:any){
    this.selectedFile = imageInput.files[0];
    this.previewImageLoad();
  }

  previewImageLoad(){
    let reader = new FileReader();
    reader.onloadend = e =>{
      this.preview_image = reader.result;
    }
    reader.readAsDataURL(this.selectedFile);
  }

  open_dialog(message:string){
    const dialogRef = this.dialog.open(DialogBodyComponent, {
      width: '550px',
      height: '200px',
      data: {
        message
      }
      
    });
    dialogRef.afterClosed().subscribe((confirm:boolean)=>{
      if(confirm){
        this.submit_blog();
      }
    })
    
  }

  open_alert_dialog(message:string){
    let dialogRef = this.dialog.open(AlertDialogBodyComponent,{
      width:'550px',
      height: '200px',
      data:{
        message
      }
    });
  }

  async submit_blog(){
      this.show_spinner = true;
      const image_data = await this.image_service.upload_image(this.selectedFile).toPromise();
      let blog = {
        title: this.title,
        content: this.content,
        feature_image:image_data["data"].link,
        tags:[]
      }

      this.tags.map((element)=>{
        blog.tags.push(element["name"])
      });

      this.blog_service.add_blog(blog).subscribe((response:any)=>{
        this.blog_id = response.id;
        this.show_spinner = false;
        this.open_alert_dialog(`Blog has been created with the id: ${this.blog_id}`);
        this.title = "";
        this.content = "";
        this.preview_image = "";
        this.tags = []; 
      });

    }
}

Explicación:

Aquí hemos creado diferentes funciones para realizar diversas operaciones. Ahora entendamos cada uno de ellos:

open_dialogue: Esta función devolverá un cuadro de diálogo para la confirmación del usuario. Esta es una función muy flexible porque podemos pasar mensajes personalizados en esta función.

open_alert_dialog: Esta función devolverá un cuadro de alerta para la confirmación del usuario. Esta también es una función flexible y acepta mensajes personalizados.

processFile: Esta función toma las imágenes y las configura previewImagepara que las imágenes que se están cargando se puedan mostrar al mismo tiempo.

Paso –5: Llamar a las API de Python

Ahora que entendemos todo el código anterior, es hora de llamar a nuestras API de Python. Entonces, abra api-calls/blog.service.tsy pegue el siguiente código:

export class BlogService {
  private add_blog_url:string = 'http://localhost:5000/add_blog';
  constructor(private http:HttpClient) { }

  add_blog(blog_props:Object){
    return this.http.post(this.add_blog_url,blog_props);
  }
}

Explicación:

Aquí llamamos a nuestra API de Python, y el punto final es add_blog, que se usa para crear una nueva publicación de blog.

Paso –6: Mostrar todas las publicaciones publicadas en la interfaz de usuario del administrador

Ahora tenemos que crear una página que mostrará todas las publicaciones del blog publicadas y le permitirá eliminar y editar el artículo. Así que ahora abre admin/all-blogs/all-blogs.component.tsy pega el siguiente código:

import { AlertDialogBodyComponent } from './../../alert-dialog-body/alert-dialog-body.component';
import { DialogBodyComponent } from 'src/app/dialog-body/dialog-body.component';
import { BlogService } from './../../api-calls/blog.service';
import { Component, OnInit, OnChanges, ChangeDetectorRef } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';

interface Blog{
  title:string,
  content:string,
  feature_image:string,
  tags: []
}

@Component({
  selector: 'app-all-blogs',
  templateUrl: './all-blogs.component.html',
  styleUrls: ['./all-blogs.component.css']
})



export class AllBlogsComponent implements OnInit {
  private blogs: Array<Blog> = [];
  private deleted_blog_id:string;
  private show_spinner:boolean = false;
  constructor(private blog_service:BlogService, private dialog:MatDialog) {}

  ngOnInit() {
    this.load_all_blogs();
  }
  
  load_all_blogs(){
    this.blog_service.get_all_blogs().subscribe((response:any)=>{
      response.all_blogs.forEach((element:any) => {
        this.blogs.push(element);
      });
    })
  }

  open_dialog(message:string, blog_id:string): void {
    let dialogRef = this.dialog.open(DialogBodyComponent,{
      data: {
        message
      },
      width: '550px',
      height:'200px'
    })

    dialogRef.afterClosed().subscribe((confirm:boolean)=>{
      if(confirm){
        this.delete_single_blog(blog_id);
      }
    });
  }

  open_alert_dialog(message:string){
    let dialogRef = this.dialog.open(AlertDialogBodyComponent,{
      width:'550px',
      height: '200px',
      data:{
        message
      }
    });
  }



  delete_single_blog(blog_id:string){
    this.show_spinner = true;
    this.blog_service.delete_blog(blog_id).subscribe((response)=>{
      if(response){
        this.show_spinner = false;
        this.open_alert_dialog("The blog was successfully deleted");
      }
    })
  }

}

Explicación:

Aquí, estamos importando el componente de diálogo de alerta y el componente de diálogo que se representará en esta página. load_all_blogs()llamará get_all_blogs()para buscar todas las publicaciones del blog. Si miras en la función delete_single_blog(), estamos pasando una cadena a la función open_alert_dialog()Una vez que se elimina el blog, enviamos un mensaje de éxito. También detendrá la ruleta; lo estamos haciendo estableciendo show_spinner= falso.

Ahora abra el archivo blog.servicey pegue el siguiente código:

private get_all_blogs_url:string = 'http://localhost:5000/blogs';
private delete_blog_url:string = 'http://localhost:5000/delete_blog/';

get_all_blogs(){
    return this.http.get(this.get_all_blogs_url);
}

delete_blog(id:string){
    return this.http.delete(this.delete_blog_url + id);
}

Explicación:

Ahora tenemos dos funciones get_all_blogs()delete_blog(), en BlogService, para hacer llamadas a la API configurando la información requerida.

Paso –7: Actualice los blogs existentes:

Hasta ahora hemos agregado la mayoría de las funcionalidades en el blog, como agregar una publicación de blog y eliminar una publicación de blog. Ahora tenemos que agregar componentes para actualizar las publicaciones de blog existentes. Abra admin/update-blog/update-blog.component.tsy pegue las siguientes líneas de código:

import { FeatureImageService } from './../../api-calls/feature-image.service';
import { AlertDialogBodyComponent } from './../../alert-dialog-body/alert-dialog-body.component';
import { DialogBodyComponent } from 'src/app/dialog-body/dialog-body.component';
import { MatDialog } from '@angular/material/dialog';
import { BlogService } from './../../api-calls/blog.service';
import { Component, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';


interface Blog{
  title:string,
  content:string,
  tags:string[],
  feature_image:any
}

@Component({
  selector: 'app-update-blog',
  templateUrl: './update-blog.component.html',
  styleUrls: ['./update-blog.component.css']
})



export class UpdateBlogComponent implements OnInit {
  private blog_id: string;
  private selectedFile:any;
  private show_spinner:boolean = false;
  private blog_props: Blog = {
    title: "",
    content: "",
    tags: [],
    feature_image: ""
  }

  constructor(private active_route:ActivatedRoute, 
              private dialog:MatDialog, 
              private blog_service:BlogService,
              private image_service:FeatureImageService
              ) { } 

  ngOnInit() {
      this.active_route.params.subscribe((response)=>{
      this.blog_id = response.id;
      this.get_blog_info();
      });
      
  }

  processFile(imageInput:any){
    this.selectedFile = imageInput.files[0];
    this.previewImageLoad();
  }

  previewImageLoad(){
    let reader = new FileReader();
    reader.onloadend = e =>{
      this.blog_props.feature_image = reader.result;
    }
    reader.readAsDataURL(this.selectedFile);
  }

  open_dialog(message:string){
    const dialogRef = this.dialog.open(DialogBodyComponent, {
      width: '550px',
      height: '200px',
      data: {
        message
      }
      
    });
    dialogRef.afterClosed().subscribe((confirm:boolean)=>{
      if(confirm){
        this.submit_blog();
      }
    })
    
  }

  open_alert_dialog(message:string){
    let dialogRef = this.dialog.open(AlertDialogBodyComponent,{
      width:'550px',
      height: '200px',
      data:{
        message
      }
    });
  }

  get_blog_info(){
    this.blog_service.get_single_blog(this.blog_id).subscribe((response:any)=>{
      this.blog_props.title = response.single_blog.title;
      this.blog_props.content = response.single_blog.content;
      this.blog_props.feature_image = response.single_blog.feature_image;
      response.single_blog.tags.forEach((element:any) => {
        this.blog_props.tags.push(element);
      });
    });
  }

  async submit_blog(){
    this.show_spinner = true;
    let image_link:any;
    if(this.selectedFile){
      const image_data = await this.image_service.upload_image(this.selectedFile).toPromise();
      image_link = image_data["data"].link;
    }
    else{
      image_link = this.blog_props.feature_image; 
    }
    
    let blog = {
      title: this.blog_props.title,
      content: this.blog_props.content,
      feature_image:image_link,
    }

    this.blog_service.update_blog(blog,this.blog_id).subscribe((response:any)=>{
      this.blog_id = response.blog_id;
      this.show_spinner = false;
      this.open_alert_dialog(`Blog with the id: ${this.blog_id} has been updated`);
    });

  }

}

Para definir un servicio, abra de blog.servicenuevo y pegue la siguiente línea de código:

private get_single_blog_url:string = 'http://localhost:5000/blog/';
private update_blog_url:string = 'http://localhost:5000/update_blog/';

get_single_blog(blog_id:string){
  return this.http.get(this.get_single_blog_url + blog_id);
}

update_blog(blog_props: Object, blog_id:string){
  return this.http.put(this.update_blog_url + blog_id, blog_props);
}

Explicación:

Si recorrió el artículo anterior donde creamos la API para este CMS sin cabeza, hemos definido un punto final de API que devolverá los detalles del blog al aceptar el idde la publicación del blog. Llegaremos a ese punto final aquí.

Paso –8: Creación de la página de inicio:

Primero crearemos componentes de la página de inicio en homepage/homepage.component.tsEntonces, abra homepage/homepage.component.tsy agregue las siguientes líneas de código:

import { BlogService } from './../api-calls/blog.service';
import { Component, OnInit } from '@angular/core';

interface Blog{
  title:string,
  feature_image:string,
  created_at:string,
  content:string
}

@Component({
  selector: 'app-homepage',
  templateUrl: './homepage.component.html',
  styleUrls: ['./homepage.component.css']
})
export class HomepageComponent implements OnInit {
  private all_blogs: Blog[] = [];
  constructor(private blog_service:BlogService) { }

  ngOnInit() {
    this.load_all_blogs();
  }

  load_all_blogs(){
    this.blog_service.get_all_blogs().subscribe((response:any)=>{
      response.all_blogs.forEach((element:any) => {
        this.all_blogs.push(element);
      });
    })
  }

}

Explicación:

Estamos importando un blog.serviceaquí para poder realizar llamadas a la API. En la inicialización, llamará a la función load_all_blogs(), que llamará get_all_blogs()desde blog.servicey buscará las publicaciones del blog y luego ejecutará un forEachciclo que empuja todas las publicaciones del blog en la página.

Tenemos una página más blog-details, para la cual tenemos que agregar un componente más blog-details.component.ts.

import { ActivatedRoute } from '@angular/router';
import { BlogService } from './../api-calls/blog.service';
import { Component, OnInit } from '@angular/core';

interface Blog{
  title:string,
  content:string,
  feature_image:string,
  tags: string[],
  created_at: string
}

@Component({
  selector: 'app-blog-details',
  templateUrl: './blog-details.component.html',
  styleUrls: ['./blog-details.component.css']
})
export class BlogDetailsComponent implements OnInit {
  private blog_id:string;
  private blog_props : Blog = {
    title: "",
    content:"",
    feature_image: "",
    tags: [],
    created_at:""
  };
  constructor(private blog_service:BlogService, private active_route:ActivatedRoute) { }

  ngOnInit() {
    this.active_route.params.subscribe((response)=>{
      this.blog_id = response.id;
      this.get_blog_details();
    })
    
  }

  get_blog_details(){
    this.blog_service.get_single_blog(this.blog_id).subscribe((response:any)=>{
      this.blog_props.title = response.single_blog.title;
      this.blog_props.content = response.single_blog.content;
      this.blog_props.feature_image = response.single_blog.feature_image;
      this.blog_props.created_at = response.single_blog.created_at;
      response.single_blog.tags.foreach((element:any)=>{
        this.blog_props.tags.push(element);
      });
    });
  }

}

Explicación:

Aquí nuevamente, estamos importando blog.servicepara hacer llamadas a la API. Al inicializar la página, llamamos get_blog_details(), que mostrará los detalles del blog en la página.

Paso –9: Configuración de la página de inicio de sesión

Hemos terminado con la configuración de la interfaz. Ahora solo tenemos que trabajar en la página de inicio de sesión. Entonces, primero agregaremos el componente de inicio de sesión. Abra login/login.component.tsy pegue el siguiente código:

import { Router } from '@angular/router';
import { AuthService } from './../auth.service';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
  private email:string;
  private password:string;
  private hide:true;
  constructor(private auth_service:AuthService,private router:Router) { }

  ngOnInit() {
  }
  
  submit_form(){
    let credentials = {
      email:this.email,
      password:this.password
    }
    this.auth_service.login(credentials).subscribe((response:any)=>{
      if(response.token){
        localStorage.setItem('auth_token', response.token);
        this.router.navigate(['/admin']);
      }
      
    })
  }

}

Explicación:

Aquí hemos creado una función submit_form(), que llamará al punto final de la API de inicio de sesión y enviará las credenciales de inicio de sesión de la página de inicio de sesión. Devolverá el token de autenticación, que guardaremos en el almacenamiento local.

Ahora abra la auth.servicepágina y pegue el siguiente código:

import { Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import {JwtHelperService} from '@auth0/angular-jwt';

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  private login_url:string = 'http://localhost:5000/login';
  constructor(private http:HttpClient, private jwtHelper:JwtHelperService,private router:Router) { }

  login(credentials:Object){
    return this.http.post(this.login_url, credentials);
  }

  is_logged_in(){
    const token = localStorage.getItem('auth_token');
    if(!token) return false

    const is_expired = this.jwtHelper.isTokenExpired(token);

    return !is_expired;
  }

  logout(){
    localStorage.removeItem('auth_token');
    this.router.navigate(['/login']);
  }
}

Explicación

Aquí estamos haciendo muchas cosas. login()se utiliza para iniciar sesión y is_logged_in()se utiliza para comprobar si el administrador ha iniciado sesión o no comprobando el valor de almacenamiento local de auth_token.

También tenemos que instalar el controlador JWT, así que ejecute el siguiente comando en la terminal:

npm install @auth0/angular-jwt

Ahora, dentro de la matriz de importaciones, app.module.tspegue el siguiente código:

JwtModule.forRoot({
config: { tokenGetter: function tokenGetter() { return localStorage.getItem('auth_token');}, whitelistedDomains: ['localhost:5000'], blacklistedRoutes: ['http://localhost:5000/login'] } })

Paso –10: Protección de la ruta de inicio de sesión:

Ahora tenemos que hacer que la página de inicio de sesión solo sea accesible cuando el usuario no haya iniciado sesión. Abra auth-guard.service.tsy pegue la siguiente línea de códigos:

import { AuthService } from './auth.service';
import { Router, CanActivate, RouterStateSnapshot, ActivatedRouteSnapshot } from '@angular/router';
import { Injectable } from '@angular/core';


@Injectable({
  providedIn: 'root'
})
export class AuthGuardService implements CanActivate{

  constructor(private auth_service:AuthService, private router:Router) { }

  canActivate(next:ActivatedRouteSnapshot,state:RouterStateSnapshot):boolean{
    if(this.auth_service.is_logged_in()) return true
    
    this.router.navigate(['/login']);
    return false;
  }
}

Una vez que se inserta el código anterior, pegue el código siguiente en app-routing.module.ts:

{path:'admin', component:AdminComponent,
canActivate:[AuthGuardService], children:[ {path:'all-blogs', component:AllBlogsComponent}, {path:'add-blog', component:AddBlogComponent}, {path:'update-blog/:id',component:UpdateBlogComponent} ] }

Explicación:

Estamos comprobando aquí si el administrador ha iniciado sesión con la función is_logged_in()Si el usuario ha iniciado sesión, permitirá el acceso a las páginas de administración internas o irá a la página de inicio de sesión.

Finalmente, todo está hecho. Suponemos que el servidor de matraces ya se está ejecutando en una terminal diferente, solo tenemos que ejecutar Angular. Así que corre ng servea la terminal y… ¡¡¡TADA !!! Puede acceder a las páginas angulares. Asegúrese de agregar algunas publicaciones de blog, o de lo contrario, solo mostrará una página en blanco en la URL raíz. También puede clonar el código ya hecho desde aquí: .https://github.com/vyomsrivastava/cms-frontend

Ultimas palabras

En esta publicación, hemos creado un sistema CMS completo usando Flask y Angular. Por supuesto, esto es solo un punto de partida y es muy flexible para muchas otras funcionalidades. Para expandir esta configuración básica, puede agregar muchas otras funcionalidades, como un sistema de administración de usuarios para permitir diferentes roles como Autor, Colaborador, Suscriptor o Administrador. Por supuesto, también puede mejorar la interfaz de usuario.

Esperamos que esto le ayude a comenzar a construir una interfaz para su backend de API CMS sin cabeza. Si tiene algún problema con el código, comente a continuación e intentaremos ayudarlo.

Publicar un comentario

0 Comentarios