Me encuentro siguiendo el curso por windows y he tenido este inconveniente a la hora de cargar el archivo .js, me indica que no estoy autorizado, alguna idea de que configuración a nivel del servicio o de mongo tenga que realizar.
Mi base de datos se llama edbase
Al ejecutar el docker-compose mostrado en el video, todo ejecuta bien, pero menos el mongo-express, que valores necesito actualizar en el manifiesto ?
<!-- <div class="wrapper" *ngIf="showModal$ | async"> -->
<div class="wrapper">
<div class="new-task">
<form [formGroup]="newTask" (ngSubmit)="saveTask()">
<div class="form-input">
<label>Titulo</label>
<input formControlName="order" type="text">
</div>
<ng-container formArrayName="item"
*ngFor="let field of getItems();let i = index" >
<!-- *ngFor="let field of formItemsGroup$ | async;let i = index" > -->
<div class="form-input"
[formGroupName]="i">
<label>{{field?.value?.key}}</label>
<input formControlName="value" type="text">
</div>
</ng-container>
<div class="form-input">
<button class="btn-primary">Guardar</button>
<button (click)="cancel()" class="btn-default">Cancelar</button>
</div>
</form>
</div>
</div>
.wrapper{
position: fixed;
width: 100%;
height: 100%;
z-index: 1;
top:0;
right:0;
background-color: rgba(0,0,0,.3);
display: flex;
align-items: center;
justify-content: center;
align-content: center;
}
.new-task{
width: 650px;
padding: 1rem;
min-height: 400px;
background-color: #fff;
box-shadow: rgba(50, 50, 93, 0.25) 0px 13px 27px -5px, rgba(0, 0, 0, 0.3) 0px 8px 16px -8px;
}
.new-task form{
display: flex;
gap: .5rem;
flex-direction: column;
}
.form-input{
display: flex;
flex-direction: column;
}
.form-input input, .form-input textarea{
border:solid 2px #DFE1E6;
background-color: #FAFBFC;
min-height: 40px;
border-radius: var(--border-radius);
padding: 0 .5rem;
}
import { Component, OnInit } from '@angular/core';
import { FormArray, FormControl, FormGroup } from '@angular/forms';
import { NewTaskService } from '@modules/task/services/new-task.service';
<a href="/u/Component" data-community-mention="USER" data-community-mention-slug="Component">@Component</a>({
selector: 'app-new-task',
templateUrl: './new-task.component.html',
styleUrls: ['./new-task.component.css']
})
export class NewTaskComponent implements OnInit {
newTask:FormGroup = new FormGroup({})
showModal$ = this.newTaskService.showModal$
constructor(
private newTaskService:NewTaskService
) { }
ngOnInit(): void {
this.newTask = new FormGroup(
{
order: new FormControl(''),
item: new FormArray([
new FormGroup(
{
key: new FormControl('Precio'),
value: new FormControl('')
}
),
new FormGroup(
{
key: new FormControl('Observacion'),
value:new FormControl('')
}
),
]),
}
)
}
getItems():any {
console.log(this.newTask.get('item'))
const list = this.newTask.get('item') as FormArray
return list.controls
}
saveTask():void {
console.log(this.newTask.value)
}
cancel():void {
this.newTaskService.setShow(false)
}
}
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
<a href="/u/Injectable" data-community-mention="USER" data-community-mention-slug="Injectable">@Injectable</a>({
providedIn: 'root'
})
export class NewTaskService {
_showModal$ = new BehaviorSubject(false)
showModal$ = this._showModal$.asObservable()
constructor() { }
public setShow(flag:boolean){
this._showModal$.next(flag)
}
}
En task-page.html agregar al final
<app-new-task></app-new-task>
En task.module.ts no olvidar importar el
ReactiveFormsModule
Les dejo las partes de código para copiar y pegar
<app-header></app-header>
<div class="task-columns">
<app-column [cardTitle]="item.label" [dataCards]="item.list"
*ngFor="let item of groupCard">
</app-column>
</div>
.imagen {
width: 200px;
height: 200px;
background-color: rgb(205, 205, 255);
}
.task-columns {
position: relative;
/* background-color: rgba(255, 0, 0, 0.103); */
display: flex;
flex-wrap: wra;
flex-direction: row;
gap: .25rem;
overflow-x: auto;
min-height: 500px;
padding: 0 1rem;
}
.cdk-drag-placeholder {
position: relative;
opacity: 1;
display: block;
width: 20rem;
transition: all ease 230ms;
cursor: move;
border-radius: 15px;
}
.cdk-drag-placeholder:after {
content: "";
position: absolute;
width: 100%;
height: 100%;
background-color: #DFDEDC;
border-radius: 15px;
top: 0;
left: 0;
}
.cdk-drag-preview {
display: block;
width: 500px;
transition: all ease 150ms;
border-radius: 15px;
background-color: transparent;
}
.cdk-drag-preview {
background-color: var(--color-secondary);
transition: all ease 150ms;
box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px;
}
/* Animate items as they're being sorted. */
.cdk-drop-list-dragging .cdk-drag {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
/* Animate an item that has been dropped. */
.cdk-drag-animating {
transition: transform 300ms cubic-bezier(0, 0, 0.2, 1);
}
groupCard:Array<any> = []
//para destruir las subscripciones
listObservables$:Array<Subscription> = []
const observer1$ = interval(1000).subscribe(res => {
console.log('Corriendo')
})
this.listObservables$ = [observer1$]
console.log(this.groupCard.length)
this.groupCard = [
{
label: 'Hola Mundo',
color: 'tomato',
list: [
{
order: 'Como instalar Angular',
items: [
{
key:'price',
value: 152
},
{
key:'time',
value: 152
},
{
key:'author',
value: {
name: 'Leifer Mendez',
avatar: ''
}
}
]
}
]
},
{
label: 'Nuevos',
color: 'tomato',
list: [
{
order: 'Como instalar Angular',
items: [
{
key:'price',
value: 152
},
{
key:'time',
value: 152
},
{
key:'author',
value: {
name: 'Leifer Mendez',
avatar: ''
}
}
]
}
]
}
]
:host {
display: block;
}
.column {
padding: .5rem;
width: 20rem;
justify-content: space-between;
}
.column .circle {
width: 15px;
height: 15px;
border-radius: 30px;
}
.column .label-column {
gap: .5rem
}
.column .name {
font-weight: 500;
}
.column .number {
font-weight: 400;
opacity: .8;
}
.cdk-drag-placeholder {
position: relative;
opacity: 1;
display: block;
width: 100%;
transition: all ease 230ms;
cursor: move;
border-radius: 15px;
}
.cdk-drag-placeholder:after {
content: "";
position: absolute;
width: 100%;
height: 100%;
background-color: #DFDEDC;
border-radius: 15px;
top: 0;
left: 0;
}
.cdk-drag-preview {
display: block;
width: 500px;
transition: all ease 150ms;
border-radius: 15px;
background-color: transparent;
}
.cdk-drag-preview .card {
transition: all ease 150ms;
transform: rotate(3deg);
box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px;
}
<div class="column display-flex">
<div class="label-column display-flex">
<span class="circle" [style.backgroundColor]="'red'"></span>
<span class="name">
{{ cardTitle }} <span class="number">({{dataCards.length}})</span>
</span>
</div>
<div class="label-column display-flex"></div>
</div>
<div class="column">
<app-card cdkDrag
[idOrder]="card.order"
[items]="card.items"
*ngFor="let card of dataCards" >
</app-card>
</div>
// 5.4
<a href="/u/Input" data-community-mention="USER" data-community-mention-slug="Input">@Input</a>() dataCards:Array<any> = []
<a href="/u/Input" data-community-mention="USER" data-community-mention-slug="Input">@Input</a>() cardTitle!:string
:host {
display: block;
}
.card {
background-color: white;
border-radius: 3px;
margin-bottom: 1rem;
min-height: 100px;
padding: .75rem
}
.card .title {
font-weight: 600;
}
.card .body {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: .35rem
}
.card .body li {
display: flex;
gap: .25rem;
font-size: 90%;
}
.card .body li span {
font-weight: 400;
}
.card .avatar-small {
width: 20px;
height: 20px;
border-radius: 5px;
object-fit: cover;
}
<div class="card">
<div class="title"> N° {{idOrder}}</div>
<ul class="body">
<ng-container *ngFor="let item of items">
<li *ngIf="['price','time'].includes(item.key)">
<i class="uil" [ngClass]="{
'uil-credit-card':item.key == 'price',
'uil-clock':item.key == 'time'
}"></i>
<span>{{item.value}}</span>
</li>
<li *ngIf="['author'].includes(item.key)" >
<img class="avatar-small" [src]="item.value.avatar" alt="">
<span>{{item.value.name}}</span>
</li>
</ng-container>
</ul>
</div>
<a href="/u/Input" data-community-mention="USER" data-community-mention-slug="Input">@Input</a>() idOrder:string|number = 0
<a href="/u/Input" data-community-mention="USER" data-community-mention-slug="Input">@Input</a>() items:Array<any> = []
Profesor una duda, en el ejemplo realizado cuando se crea un .row, no se supone que los .col que debe contener el row, deben de dar la suma = a 12 ?
<div class="container">
<div class="row">
<div class="col-sm-6 col-md-4 col-lg 6 col-xl-10 bg-primary border">1</div>
<div class="col-sm-6 col-md-4 col-lg 6 col-xl-1 bg-primary border">2</div>
<div class="col-sm-12 col-md-4 col-lg 6 col-xl-1 bg-primary border">3</div>
</div>
</div>
Por ejemplo para el md marca la cifra correcta, para el xl igual, pero en sm (24) y en lg(18)
product.js
const menu = [
{id:100,name:'Papa Fritas', price:100},
{id:200,name:'Hamburguesa Especial', price:50},
{id:300,name:'Hamburguesa Mixta', price:40},
{id:400,name:'Pizza', price:80},
{id:500,name:'Soda', price:10},
]
index.js
const usuario={nombre:'Alfredo', edad:'25', deuda:0}
let pedidoUser = []
let ganancias = 0
//Lista de los productos del menu
const vermenu = () => {
console.log("ID - MENU - PRECIO")
menu.forEach(carta => console.log(`Id: ${carta.id} Nombre:${carta.name} Precio:${carta.price}`))
return ''
}
//Formulario para realizar una orden
const pedirProducto = codigo => {
while(codigo === null || codigo === undefined){
codigo = prompt("Digite el codigo")
}
const ProductValid = menu.find(prod => prod.id === parseInt(codigo))
if(!ProductValid)
{
alert("Digite un codigo de producto valido")
pedirProducto()
}
else{
alert(`Has pedido una ${ProductValid.name} de S/.${ProductValid.price} se agregara a tu cuenta`)
pedidoUser.push(ProductValid)
let newpedido = prompt('Desea seguir ordenando ? Responsa si ó no ')
if(newpedido === "si")
{
pedirProducto()
}
else{
verPedido()
}
}
}
//Método para ver los pedidos realizados
const verPedido = () => pedidoUser
vermenu()
const calcularCosto = () => {
let costo = 0
pedidoUser.forEach(prod => costo+= prod.price)
usuario.deuda = costo
return usuario.deuda
}
const reporteVentas = () => `El día de hoy se ha ganado S/.${ganancias}`
const pagarPedido = () => {
let monto
do {
monto = parseInt(prompt("Ingrese la cantidad de dinero a pagar"))
} while (monto <0 || isNaN(monto) )
switch(true)
{
case (monto === 0):
console.log('No puedes pagar con 0 soles')
break;
case (monto > usuario.deuda):
let vuelto = (monto - usuario.deuda).toFixed(2)
alert(`Su deuda es de S/.${usuario.deuda} has pagado con S/.${monto} su vuelto es de S/.${vuelto}`)
ganancias+= usuario.deuda
usuario.deuda = 0
break
case (monto === usuario.deuda):
alert(`Su deuda es de S/.${usuario.deuda} Has pagado con S/.${monto} no hay vuelto`)
ganancias+= usuario.deuda
usuario.deuda = 0
break
case (monto < usuario.deuda):
alert('El dinero no te alcanza para cancelar tu deuda')
break
default:
alert('No tienes nada por pagar')
}
}
//Finaliza el pedido y se encarga de realizar el cálculo y cobro
const finalizarPedido = () => {
calcularCosto()
pedidoUser = []
do {
pagarPedido()
} while (usuario.deuda > 0);
}
Como sabemos en nuestro método recibimos un parámetro de tipo genérico el cual tiene por nombre socialNetwork, y para este caso lo declaramos como el tipo de clase SocialNetwork dentro de la variable socialNetworkItem, más adelante definimos una condicional para identificar si el objeto pertenece al de tipo SocialNetworkWithGroups.
public string GetSocialNetworkStats<T>(T socialNetwork)
{
var socialNetworkItem = socialNetwork as SocialNetWork
if (socialNetworkItem is SocialNetworkWithGroups)
{
....
}
return ...
}
Este procedimiento me llevo a pensar una manera de detectar el tipo de objeto que se esta recibiendo sin tener que declararlo directamente socialNetworkItem = socialNetwork as SocialNetWork, en mi caso para evitar demasiadas declaraciones cuando se tengan distintos tipos. De tal forma que en mi búsqueda encontré las siguientes opciones para realizarlo.
De esta forma solo logre detectar el tipo, más no minificar la declaración para el respectivo tipo del objeto, puesto que una vez detectado, si pertenece a un tipo específico tendré que declarar dentro de la condicional al tipo que pertenece, aún no se acerca a lo que busco.
Type tipo = typeof(T);
if (tipo == typeof(SocialNetworkWithGroups))
{
Console.WriteLine("Es una red social con grupos");
}
else if (tipo == typeof(SocialNetwork))
{
Console.WriteLine("Es una red social");
}
Con esta otra forma evitamos la declaración de un objeto Type para identificar el tipo de dato que estamos recibiendo en nuestro parámetro, mediante el método .GetType(), adicionalmente esta opción tiene algo que la distingue de las opciones 1 y 3, que estaré explicando luego. La contra con esta opción es que nuevamente nos topamos con la necesidad de tener que declarar el tipo de dato al que pertenece una vez pasada la condicional, es una opción pero no la que deseo.
if (socialNetwork.GetType() == typeof(SocialNetwork))
{
Console.WriteLine("Es una red social");
}
else if (socialNetwork.GetType() == typeof(SocialNetworkWithGroups))
{
Console.WriteLine("Es una red social con grupos");
}
La última de todas es volver al inicio, así es, pero esta vez sin la necesidad de tipar la declaración del tipo de objeto luego de pasar la condición, de esta forma:
if (socialNetwork is SocialNetworkWithGroups sng)
{
Console.WriteLine($"{sng.Name} Es una red social con grupos");
}
else if (socialNetwork is SocialNetwork sn)
{
Console.WriteLine($"{sn.Name} Es una red social");
}
Logrando así declarar el tipo de objeto al que pertenezca e identificarlo mediante la misma condicional, obviando así la declaración antes o después que alguna condicional se cumpla.
var socialNetworkItem = socialNetwork as SocialNetWork
var socialNetworWithGroupItem =socialNetwork as SocialNetworkWithGroups
Respecto a la característica que comparten las opciones 2 y 3, es el orden de la condicional, como se vio en esta sesión, nuestra clase SocialNetworkWithGroups hereda de SocialNetwork, por lo cual en las opciones mencionadas, si la primera de nuestras condicionales se igual a la clase de la cual se esta heredando y luego le siguen otras clases que heredan de esa misma tendremos el siguiente resultado.
//Digamos que el socialNetwork que se envía como parámetro es de tipo WithGroups:
if (socialNetwork is SocialNetwork sn) //Esto es verdadero
//se cumple la condicional
else if (socialNetwork is SocialNetworkWithGroups sng) //Esto también
//No llega hasta aquí
else if (socialNetwork is SocialNetworkWithGroups2 sng2)
...
Esto sucede debido al factor de la herencia, es por ello que en la condicional, las clases que heredan de la principal deben de colocarse antes de esta, para que puedan ser evaluadas.
Ahora con las declaración de las variables ya simplificadas, en caso que tenga más clases que hereden de SocialNetwork obtendre un conjunto anidado de condicionales
if (socialNetwork is SocialNetworkWithGroups stypefour)
.....
else if (socialNetwork is SocialNetworkWithGroupsThree stypethree)
.....
else if (socialNetwork is SocialNetworkWithGroupsTwo stypetwo)
.....
else if (socialNetwork is SocialNetworkWithGroupsTOne stypeone)
.....
else if (socialNetwork is SocialNetwork sn)
.....
Mi consulta sería, cual podría ser una solución para evitar un fuerte anidado en ese tipo de situaciones. Si bien esta la alternativa de usar un switch, existe algo más optimizado ? Por ejemplo algo para detectar el tipo de dato directamente sin tener que pasar por demasiadas validaciones.
Presente un problema con la librería lxml empleando pycharm en Windows
Al parecer se requiere hacer la instalación directamente en la terminal de windows
ejecutando un : pip install lxml
por si no les funciona esa solución aquí dejo 3 referencias para su solución en windows.
https://stackoverflow.com/questions/29440482/how-to-install-lxml-on-windows https://stackoverflow.com/questions/31750863/python-cant-find-or-install-lxml https://stackoverflow.com/questions/37653018/cant-install-lxml-on-python-3-5