Can we create a complete site in Python? or do we need Java Scripts? [closed]

Can a complete website be created using only Python, or is it necessary to incorporate JavaScript for certain functionalities? I’m curious about the role of Python in web development, particularly through frameworks like Django or Flask, and whether they can handle all aspects of building a website, including frontend interactivity. Additionally, if JavaScript is required, how can it be seamlessly integrated with Python to create a cohesive and fully functional web application? Your insights into the role of both languages in web development would be highly valuable.

Want a Detaild Answer

Conditionally Render Navigation Links Based on User Authentication in Next.js

I’m working on a Next.js project where I want to conditionally render navigation links in the header based on user authentication. I have a NavBar that handles the rendering of links.

For authenticated users, I want to display the links Home,Profile, and Sign out. For non-authenticated users, the links should be Login and View All Stores.

Currently, I’m using the session to determine whether a user is authenticated or not. However, when the user is not authenticated, the entire navbar is hidden. I want to modify this behavior so that the navbar is always visible, but only the links are conditionally displayed based on authentication status.

Layout.tsx

export const inter = Inter({ subsets: ['latin'] });

//tried adding this
export const revalidate = 0;
export const dynamic = "force-dynamic";

export const metadata = {
  title: 'Water Refilling Station',
  description: 'Generated by Next.js',
}

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {

  const supabase = createServerComponentClient({cookies});

  const {
    data: { session },
  } = await supabase.auth.getSession();

  const accessToken = session?.access_token || null;
  return (
    <html lang="en">
      <body className={`${inter.className} antialiased`}>
      <NavBar session={session}/>
      <AuthProvider accessToken={accessToken}>{children}</AuthProvider>
      </body>
    </html>
  )
}

NavBarComponent
‘use client’

const navigation = [
  { name: 'Home', href: '/', },
  { name: 'Profile', href: '/Profile'},
]

function classNames(...classes: string[]) {
  return classes.filter(Boolean).join(' ')
}

export default function NavbarComponent() {
    const pathname = usePathname()
  return (
    <Disclosure as="nav" className="bg-gray-800">
      {({ open }) => (
        <>
          <div className="mx-auto max-w-7xl px-2 sm:px-6 lg:px-8">
            <div className="relative flex h-16 items-center justify-between">
              <div className="absolute inset-y-0 left-0 flex items-center sm:hidden">
                {/* Mobile menu button*/}
                <Disclosure.Button className="relative inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white">
                  <span className="absolute -inset-0.5" />
                  <span className="sr-only">Open main menu</span>
                  {open ? (
                    <XMarkIcon className="block h-6 w-6" aria-hidden="true" />
                  ) : (
                    <Bars3Icon className="block h-6 w-6" aria-hidden="true" />
                  )}
                </Disclosure.Button>
              </div>
              <div className="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start">
                <div className="flex flex-shrink-0 items-center">
                  <img
                    className="h-8 w-auto"
                    src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=500"
                    alt="Your Company"
                  />
                </div>
                   <div className="hidden sm:ml-6 sm:block">
                   <div className="flex space-x-4">
                     {navigation.map((item) => (
                       <Link
                         key={item.name}
                         href={item.href}
                         className={
                            item.href === pathname
                              ? 'bg-gray-900 text-white rounded-md px-3 py-2 text-sm font-medium'
                              : 'text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium'
                          }
                          aria-current={item.href === pathname ? 'page' : undefined}
                       >
                         {item.name}
                       </Link>
                     ))}
                   </div>
                 </div>
              </div>
              <div className="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0">
              <form action="/auth/signout" method="post">
                  <button type="submit"
                  className="relative rounded-full bg-gray-800 p-1 text-gray-400 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800"
                  >
                    Sign out
                  </button>
                </form>
                
               </div>
            </div>
          </div>
          

          <Disclosure.Panel className="sm:hidden">
            <div className="space-y-1 px-2 pb-3 pt-2">
              {navigation.map((item) => (
                <Disclosure.Button
                  key={item.name}
                  as="a"
                  href={item.href}
                    className={classNames(
                    item.href === pathname ? 'bg-gray-900 text-white' : 'text-gray-300 hover:bg-gray-700 hover:text-white',
                    'block rounded-md px-3 py-2 text-base font-medium'
                  )}
                  aria-current={item.href === pathname ? 'page' : undefined}
                >
                  {item.name}
                </Disclosure.Button>
              ))}
            </div>
          </Disclosure.Panel>
        </>
      )}
    </Disclosure>
  )
}

To be able to use the session, I added this component and this is the one that is being imported to the Layout.tsx. I am using this component because I cannot directly use the session on the NavBarComponent because session is from a server. Hence, it will cause an error if I try to use the session on the NavBarComponent

import NavbarComponent from "./NavBarComponent";

const NavBar = async ({ session} : {session: any}) => {  
    return ( 
        <div>
            {/* Links here */}
            
            {session &&  <NavbarComponent/>}
            {/* Button for Login and Logout */}
        </div>
     );
}
 
export default NavBar;

I want to ensure that the navbar is always visible and only the links are conditionally displayed based on the user’s authentication status. What modifications should I make to achieve this behavior?

Any help or suggestions would be greatly appreciated. Thank you!

How to open PDF in new tab in safari mobile

It’s the year 2023 and I’ve already found a few posts on the same topic. These go back to 2010. Unfortunately there is no solution that is adequate for me.

I have the following code in my website and I want to open the downloaded PDF (as a blob) in a new tab in the browser.

const link = document.createElement( 'a' );
myFetch( 'report/getBalanceSheet',
    {year: balanceSheetYear},
    {
        method: 'get',
        headers: {
            'Authorization': 'Bearer ' + UserService.getToken(),
            'Content-Type': 'application/json'
        }
    })
    .then(async res => {
        // check for error response
        if ( !res.ok ) {
            // get error message from body or default to response statusText
            const error = res.status + " " + res.statusText;
            return Promise.reject( error );
        }

        const blob = await res.blob();

        if(blob.size === 0){
            //Empty file
            return;
        }
        link.href = URL.createObjectURL( blob );
        link.target="_blank"
        link.dispatchEvent( new MouseEvent( 'click' ) );
        URL.revokeObjectURL( link.href );
    })
    .catch( ( error ) => {
        //Some error handling
    } );

It works in all browsers except Safari Mobile.

I know I could change the link.target = "_blank" to link.download = "balancesheet.pdf" but then all browsers would offer me the file as a download, but I just want to display it in a new tab.

Angular – Recursive RxJS Observables Execution Order Issue

I am facing an issue with the execution order of recursive RxJS Observables in an Angular application. I have a service, RefreshReportService, which is responsible for refreshing reports. The refreshreport method is designed to refresh a report and its nested reports recursively.

The problem is that the recursive calls seem to be running in parallel instead of waiting for the completion of the previous one. Here is a simplified version of the code:

refreshreport(report_name: string): Observable<any> {
    let operations_list: any = [];
    let primary_key: string = "";

    return new Observable((observer) => {
        this.ifreportisfromotherreports(report_name, (nestedreports: any[]) => {
            if (nestedreports) {
                const recursiveCalls = nestedreports.map((nested_report_name) => {
                    return this.refreshreport(nested_report_name);
                });

                from(recursiveCalls).pipe(
                    concatMap((recursiveCall) => recursiveCall)
                ).subscribe({
                    next: (response: any) => { console.log(response); },
                    error: (err) => { console.log(err); },
                    complete: () => {
                        // Continue with the rest of the logic after recursive calls
                        observer.complete();
                    }
                });
            } 
            const token = localStorage.getItem('auth-token');
            const headers = new HttpHeaders({
                'Authorization': `token ${token}`
            });

            const formData = new FormData();
            formData.append('report_name', report_name);

            this.http.post('http://127.0.0.1:8000/getreportoperationslist', formData, { headers, withCredentials: true }).subscribe({
                next: (response: any) => {
                    operations_list = response.operations_list;
                    primary_key = response.primary_key;
                },
                error: (err) => {
                    console.log(err);
                },
                complete: () => {
                    const updateapicalls: Observable<any>[] = [];

                    operations_list.forEach((operation: any) => {
                        updateapicalls.push(this.createRequestObservable(operation));
                    });

                    from(updateapicalls).pipe(
                        concatMap((observable) => observable)
                    ).subscribe({
                        next: (response: any) => { console.log(response); },
                        error: (err) => { console.log(err); },
                        complete: () => {
                            this.DeleteReport(report_name, primary_key);
                            observer.complete(); // Notify the outer observer that this recursion is complete
                        }
                    });
                }
            });           
        });
    });
}

I want the recursive calls to run sequentially, waiting for the completion of the previous one before moving on to the next. Any insights into how I can achieve this would be greatly appreciated!

enter image description here

This is snap of the networks tab in here, the first one is of the most-outer function, while the second one is of the recursive function (which is correct), but the things screw up from the 3rd one, which of the outer one.. and further calls are all incorrect order of calls

I tried to run the code, but the order is not correct, i expected correct order of calling, first the function calls of the inside one’s and then the outer one’s.

Highlight charts Automatic zooming problem

Currently, bootstrapping is used to
We are building the site.

I have the chart period to show 100 days,
It is in col-8 and when I make it narrower, it auto-zooms,
The chart is not displayed for 100 days.

When I display it at full width, it is displayed without any problem.
I would like to know the cause and solution.

<div class="container">
    <div class="row g-5">
        <div class="col-md-8">
            <div id="charts">
                <div class="" id="container" style="height: 700px; min-width: 310px"></div>
            </div>
         </div>
     </div>
</div>

< script > (async() => {
  const data = await fetch("/crypto_price/{{ crypto.id }}?days_range=100").then(response => response.json());
  // split the data set into ohlc and volume
  const ohlc = [],
    volume = [],
    dataLength = data.length,
    // set the allowed units for data grouping
    groupingUnits = [
      ['day', // unit name
        [1] // allowed multiples
      ]
    ];
  for (let i = 0; i < dataLength; i += 1) {
    ohlc.push([
      data[i][0], // the date
      data[i][1], // open
      data[i][2], // high
      data[i][3], // low
      data[i][4] // close
    ]);
    volume.push([
      data[i][0], // the date
      data[i][5] // the volume
    ]);
  }
  // create the chart
  Highcharts.stockChart('container', {
    rangeSelector: {
      selected: 1
    },
    title: {
      text: "{{ crypto.coin_name }} Chart"
    },
    yAxis: [{
      labels: {
        align: 'right',
        x: -3
      },
      title: {
        text: 'OHLC'
      },
      height: '60%',
      lineWidth: 2,
      resize: {
        enabled: true
      }
    }, {
      labels: {
        align: 'right',
        x: -3
      },
      title: {
        text: 'Volume'
      },
      top: '65%',
      height: '35%',
      offset: 0,
      lineWidth: 2
    }],
    tooltip: {
      split: true
    },
    series: [{
      type: 'candlestick',
      name: "{{ crypto.coin_name }}",
      data: ohlc,
      dataGrouping: {
        units: groupingUnits
      }
    }, {
      type: 'column',
      name: 'Volume',
      data: volume,
      yAxis: 1,
      dataGrouping: {
        units: groupingUnits
      }
    }]
  });
})(); < /script>
``
`

I tried disabling rangeSelector, and responsive settings, but the chart remained zoomed

Filter table – every table row contains a dropdown

I have a datatable and every row should include a select item with several options, those are just examples.
On top of the table is the default search bar and I want to filter my rows by the text of the selected items.
Currently when I search for “plan” every row is shown no matter what option is selected.
When I type anything despite of “plan”, “do”, “check”, “act” all rows are gone like it should, I guess it doesn’t only search for the selected value.

I have my example code like this

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Data Table with Filters</title>
    <script src="javaScript/jquery-3.1.1.js"></script>
    <script src="javaScript/jquery.tablesorter.js"></script>
    <script src="javaScript/jquery-ui.min.js"></script>
    <script src="javaScript/jquery-core-validate.js"></script>
    <link rel="stylesheet" href="https://cdn.datatables.net/1.13.7/css/jquery.dataTables.css" />
    <script src="https://cdn.datatables.net/1.13.7/js/jquery.dataTables.js"></script>
</head>
<body>

    <table id="myTable" class="display">
        <thead>
            <tr>
                <th>Name</th>
                <th>Action</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Chris</td>
                <td>
                    <select>
                        <option value="0">Plan</option>
                        <option value="1">Do</option>
                        <option value="2">Check</option>
                        <option value="3">Act</option>
                    </select>
                </td>
            </tr>
            <tr>
                <td>Anna</td>
                <td>
                    <select>
                        <option value="0">Plan</option>
                        <option value="1">Do</option>
                        <option value="2">Check</option>
                        <option value="3">Act</option>
                    </select>
                </td>
            </tr>
        </tbody>
    </table>    

<script>
    let table = new DataTable('#myTable');
    $(document).ready(function () {
        // Setup - add a text input to each footer cell
        $('#myDataTable thead tr')
            .clone(true)
            .addClass('filters')
            .appendTo('#myDataTable thead');
        var table = $('#myDataTable').DataTable({
            orderCellsTop: true,
            fixedHeader: true,
            initComplete: function () {
                var api = this.api();
                // For each column
                api
                    .columns()
                    .eq(0)
                    .each(function (colIdx) {
                        // Set the header cell to contain the input element
                        var cell = $('.filters th').eq(
                            $(api.column(colIdx).header()).index()
                        );
                        var title = $(cell).text();
                        $(cell).html('<input type="text" placeholder="' + title + '" />');
                        // On every keypress in this input
                        $(
                            'input',
                            $('.filters th').eq($(api.column(colIdx).header()).index())
                        )
                            .off('keyup change')
                            .on('change', function (e) {
                                // Get the search value
                                $(this).attr('title', $(this).val());
                                var regexr = '({search})'; //$(this).parents('th').find('select').val();
                                var cursorPosition = this.selectionStart;
                                // Search the column for that value
                                api
                                    .column(colIdx)
                                    .search(
                                        this.value != ''
                                            ? regexr.replace('{search}', '(((' + this.value + ')))')
                                            : '',
                                        this.value != '',
                                        this.value == ''
                                    )
                                    .draw();
                            })
                            .on('keyup', function (e) {
                                e.stopPropagation();
                                $(this).trigger('change');
                                $(this)
                                    .focus()[0]
                                    .setSelectionRange(cursorPosition, cursorPosition);
                            });
                    });
            },
        });
    });
</script>

</body>
</html>

Annotate Javascript Class Constructor with JSDoc Custom Type

I defined a custom type in JSDoc like this:

/**
  * @typedef {{
  *   myProperty: number
  * }} MyType
  */

Now I annotate a class with it like this:

/**
  * @constructor
  * @extends {MyType}
  */
function MyClass() {
    this.myProperty = 123;
}

However, when I try to assign an instance of the class to a variable I annotated with the type, my IDE (IntelliJ IDEA) gives me an error: “Initializer type MyClass is not assignable to variable type MyType“.

/** @type {MyType} */
let myInstance = new MyClass();

I suspect that “initializer types” work somehow differently but I couldn’t figure out how. I also tried to use @augments or @implements annotations but it didn’t help.

How do I send an OTP to a phone using firebase JavaScript?

I have watched a lot of tutorials but just cant seem to make it work. My phone simply does not receive any OTP from firebase. Other users have faced this problem, but not with JavaScript.

Here is the code:

// Initialize Firebase
firebase.initializeApp(firebaseConfig);
const auth = firebase.auth();
const database = firebase.database();

var verificationId;

function sendVerificationCode() {
  var phoneNumber = document.getElementById("phoneNumber").value;

  firebase
    .auth()
    .signInWithPhoneNumber(phoneNumber, window.recaptchaVerifier)
    .then((confirmationResult) => {
      // SMS sent. Prompt user to type the code from the message
      window.confirmationResult = confirmationResult;
      verificationId = confirmationResult.verificationId;
      alert("Verification code sent to the phone number.");
      document.getElementById("signInBtn").disabled = false;
    })
    .catch((error) => {
      console.error("Error sending verification code:", error);
    });
}

function signInWithPhoneNumber() {
  var verificationCode = getElementById("verificationCode").value;

  var credential = firebase.auth.PhoneAuthProvider.credential(
    verificationId,
    verificationCode
  );

  firebase
    .auth()
    .signInWithCredential(credential)
    .then((userCredential) => {
      // Signed in
      var user = userCredential.user;
      document.getElementById("userInfo").innerHTML =
        "Signed in as: " + user.phoneNumber;
    })
    .catch((error) => {
      var errorCode = error.code;
      var errorMessage = error.message;
      alert("Error: " + errorMessage);
    });
}
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>User Login</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/firebase/7.14.1-0/firebase.js"></script>
    <script src="https://www.google.com/recaptcha/api.js" async defer></script>
    <script src="login.js"></script>
</head>

<body>
    <form id="phoneSignInForm">
        <label for="phoneNumber">Phone Number:</label>
        <input type="tel" id="phoneNumber" name="phoneNumber" required><br>

        <!-- <div id="recaptcha-container"></div> -->
    
        <button type="button" onclick="sendVerificationCode()">Send Verification Code</button><br>
    
        <label for="verificationCode">Verification Code:</label>
        <input type="text" id="verificationCode" name="verificationCode" required><br>
    
        <button type="button" id="signInBtn" onclick="signInWithPhoneNumber()" disabled>Sign In</button>
    </form>

</body>

</html>

I am not even getting the “Verification code sent to phone number” alert.

This is the console message I received:

Uncaught 
w i
a: null
code: "auth/argument-error"
message: "signInWithPhoneNumber failed: Second argument "applicationVerifier" must be an implementation of firebase.auth.ApplicationVerifier."
[[Prototype]]: Error

Please tell me where the problem is and how to solve it.

NgxAdmin freezes when load large Amount of nested data in Angular 11

using get by id API we fetch data for particular id in Angular 11

this is our form group

export class PromotionsService extends HttpService<Promotion> {
  form: FormGroup;
  
  constructor(public http: HttpClient, private fb: FormBuilder) {
    super('promotions', http);
    this.resetForm();
  }

  resetForm() {
    this.form = this.fb.group({
      siteCodeId: ['', Validators.required],
      description: ['', Validators.required],
      promotionDealsTitle: ['', Validators.required],
      flightRegionPromotions: this.fb.array([], Validators.required),
    });
  }
  createFlightRegionPromotion(flightRegionPromotionOrder: number) {
    return this.fb.group({
      id: [0],
      flightRegionId: ['', Validators.required],
      status: [true],
      order: [
        flightRegionPromotionOrder,
        [Validators.required, Validators.min(1)],
      ],
      promotionDeals: this.fb.array(
        [this.createPromotionDeal(1)],
        Validators.required,
      ),
    });
  }

  addFlightRegionPromotion(flightRegionPromotionOrder: number) {
    const flightRegionPromotions = this.form.get(
      'flightRegionPromotions',
    ) as FormArray;

    flightRegionPromotions.push(
      this.createFlightRegionPromotion(flightRegionPromotionOrder),
    );
  }
  removeFlightRegionPromotion(removeIndex: number) {
    const flightRegionPromotions = this.form.get(
      'flightRegionPromotions',
    ) as FormArray;
  flightRegionPromotions.removeAt(removeIndex);
  }

  createPromotionDeal(order: number) {
    return this.fb.group({
      id: [0],
      flightRegionPromotionId: [''],
      status: [true],
      fromDestinationsListId: ['', Validators.required],
      toDestinationsListId: ['', Validators.required],
      airlineId: ['', Validators.required],
      price: ['', Validators.required],
      currency: ['', Validators.required],
      order: [order, [Validators.required, Validators.min(1)]],
      image: this.fb.group({
        path: ['', Validators.required],
        type: [''],
        alt: [''],
      }),
    });
  }

  addPromotionDeal(
    flightRegionPromotionIndex: number,
    promotionDealOrder: number,
  ) {
    const flightRegionPromotions = this.form.get(
      'flightRegionPromotions',
    ) as FormArray;
    const promotionDeals = flightRegionPromotions.controls[
      flightRegionPromotionIndex
    ].get('promotionDeals') as FormArray;

    promotionDeals.push(this.createPromotionDeal(promotionDealOrder));
  }

  removePromotionDeal(
    flightRegionPromotionIndex: number,
    promotionDealIndex: number,
  ) {
    const flightRegionPromotions = (
      this.form.get('flightRegionPromotions') as FormArray
    ).controls[flightRegionPromotionIndex];

    const promotionDeals = flightRegionPromotions.get(
      'promotionDeals',
    ) as FormArray;
  
// **TYPESCRIPT FILE**

@Component({
  selector: 'ngx-promotions-edit',
  templateUrl: './promotions-edit.component.html',
  styleUrls: ['./promotions-edit.component.scss'],
  // changeDetection: ChangeDetectionStrategy.OnPush
})
export class PromotionsEditComponent
  extends PromotionsCreateComponent
  implements OnInit, OnDestroy, AfterViewChecked, AfterViewInit {
  private destroy$ = new Subject<void>();
  id: number;
  public Editor = ClassicEditor;
flightRegionData:FlightRegionPromotion[]=[];

  constructor(
    public siteCodesService: SiteCodesService,
    public toastrService: NbToastrService,
    public router: Router,
    public cdRef: ChangeDetectorRef,
    public mediaUploadService: MediaUploadService,
    public generalService: GeneralService,
    public authService: AuthService,
    public promotionsService: PromotionsService,
    public flightRegionService: FlightRegionService,
    public hotelbedsService: HotelbedsService,
    public route: ActivatedRoute,
    private fb: FormBuilder,
  ) {
    super(
      siteCodesService,
      toastrService,
      router,
      cdRef,
      mediaUploadService,
      generalService,
      authService,
      promotionsService,
      flightRegionService,
      hotelbedsService,
    );

    route.params.subscribe((params) => {
      this.id = params.id;
    });
  }

  ngOnInit(): void {
    this.loadData();
      }
  }

  ngAfterViewInit() {
    // setInterval(() => {
    //   const expirationTime = localStorage.getItem(
    //     `promotions-expirationTime${this.id}`,
    //   );

    //   if (expirationTime != null) {
    //     const currentTime = new Date().getTime();
    //     const expr = new Date(parseInt(expirationTime, 10)).getTime();
    //     const different = expr - currentTime;
    //     const remainMinutes = Math.floor(different / (60 * 1000));
    //     const remainSeconds = Math.floor((different % (60 * 1000)) / 1000);

    //     this.minutes.nativeElement.innerText = remainMinutes.toLocaleString(
    //       'en-GB',
    //       { minimumIntegerDigits: 2, useGrouping: false },
    //     );
    //     this.seconds.nativeElement.innerText = remainSeconds.toLocaleString(
    //       'en-GB',
    //       { minimumIntegerDigits: 2, useGrouping: false },
    //     );

    //     if (remainMinutes <= 0 && remainSeconds <= 0) {
    //       localStorage.removeItem(`promotions-expirationTime${this.id}`);
    //       if (this instanceof PromotionsEditComponent) {
    //         this.toastrService.show('Time Out', `Time Out`, {
    //           status: 'danger',
    //         });
  
    //       }
    //     }
    //   }
    // }, 1000);
  }

  loadData(){
    forkJoin([  this.generalService.getAllDestinationList(),
      this.siteCodesService.all(),
      this.flightRegionService.getAllFlightRegions(),
      this.generalService.getAllAirlines(),
      this.hotelbedsService.getAllCurrencyList(),
      this.promotionsService.find(this.id)
    ]).subscribe(([destinationList,sites,flightRegions,airlines,currencies,promotion])=>{
     this.originalDestinationList= destinationList;
     this.sites=sites;
     this.flightRegions=flightRegions;
     this.originalAirlines=airlines;
     this.currencies=currencies;
     this.getAllDestinationList();
     this.getAllSites();
     this.getAllAirlines();
     this.getHBCurrencyList();
     this.fetchPromotion(promotion);

     this.loading = false;
     
    },
    (error) => {
      this.loading = false
    })
  }

  fetchPromotion(promotion:Promotion) {
  
    if (promotion) {
      if (promotion.video == null)
        this.promotionForm.get('video.path').setValue('');

      (this.promotionForm.get('heroImages') as FormArray).clear();

      if (promotion.heroImages != null) {
        promotion.heroImages.map((image) => {
          (this.promotionForm.get('heroImages') as FormArray).push(
            this.fb.group({
              path: new FormControl(image.path),
              alt: new FormControl(image.alt),
              type: new FormControl(image.type),
            }),
          );
        });
      }

      const flightRegionPromotions = this.promotionForm.get(
        'flightRegionPromotions',
      ) as FormArray;
this.flightRegionData=promotion.flightRegionPromotions;
      flightRegionPromotions.clear();
  this.promotionForm.patchValue(promotion);
      this.loading = false;
    
    }
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }

  onNextDataAddHandler(){
    this.promotionFormStepper.next();
    const stepIndex = this.promotionFormStepper.selectedIndex;
if (this.flightRegionData != null) {
  const flightRegionPromotions = this.promotionForm.get(
    'flightRegionPromotions',
  ) as FormArray;
        this.flightRegionData.forEach((region, regionIndex) => {
          let promotionDeals: FormGroup[] = [];
          if (region.promotionDeals != null) {
            promotionDeals = region.promotionDeals.map(
              (deal, dealIndex) => {
                return this.fb.group({
                  id: new FormControl(deal?.id),
                  flightRegionPromotionId: new FormControl(
                    deal?.flightRegionPromotionId,
                  ),
                  status: new FormControl(deal?.status),
                  fromDestinationsListId: new FormControl(
                    deal?.fromDestinationsListId,
                    Validators.required,
                  ),
                  toDestinationsListId: new FormControl(
                    deal?.toDestinationsListId,
                    Validators.required,
                  ),
                  airlineId: new FormControl(
                    deal?.airlineId,
                    Validators.required,
                  ),
                  price: new FormControl(deal?.price, Validators.required),
                  currency: new FormControl(
                    deal?.currency,
                    Validators.required,
                  ),
                  order: new FormControl(deal?.order, [
                    Validators.required,
                    Validators.min(1),
                  ]),
                  image: new FormGroup({
                    path: new FormControl(
                      deal?.image?.path,
                      Validators.required,
                    ),
                    type: new FormControl(deal?.image?.type),
                    alt: new FormControl(deal?.image?.alt),
                  }),
                });
              },
            );
          }
          flightRegionPromotions.push(
            this.fb.group({
              id: [region.id],
              flightRegionId: [region.flightRegionId],
              status: [region.status],
              order: [
                region.order,
                [Validators.required, Validators.min(1)],
              ],
              promotionDeals: this.fb.array(promotionDeals),
            }),
          );
        });
      }
  }
}
<nb-card [ngClass]="{ 'edit-promotion-card': loading === true }">
  <nb-card-header class="d-flex justify-content-between align-items-center">
    <span> Edit Promotion : {{ id }} </span>
  </nb-card-header>
  <nb-card-body *ngIf="loading" class="edit-nb-card-body">
    <ngx-loader> </ngx-loader
  ></nb-card-body>
  <nb-card-body>
    <form [formGroup]="promotionForm">
      <nb-stepper #promotionFormStepper orientation="horizontal">
        <!--details-->
        <nb-step [label]="details" completed>
          <ng-template #details>Details</ng-template>
          <nb-card>
            <nb-card-body>
              <div class="row">
                
                <div class="col-md-6">
                  <div class="form-group">
                    <label for="descriptionTitle" class="label"
                      >Description Title</label
                    >
                    <input
                      type="text"
                      nbInput
                      fullWidth
                      id="descriptionTitle"
                      placeholder=""
                      formControlName="descriptionTitle"
                      class="is-invalid"
                    />
                  </div>
                </div>
             
                </div>
              </div>
            </nb-card-body>
          </nb-card>
          <!-- nbStepperNext -->
          <div class="row no-gutters justify-content-end w-100">
            <button nbButton  (click)="onNextDataAddHandler()" class="next-btn">next</button>
          </div>
        </nb-step>
        <nb-step [label]="promotiondeals" completed>
          <ng-template #promotiondeals>Promotion Deals</ng-template>
          <nb-card  formArrayName="flightRegionPromotions"
            *ngFor="
              let region of flightRegionPromotionsControls;
              let regionIndex = index
            "
          >
            <!-- formGroupName regionIndex" START-->
            <div [formGroupName]="regionIndex">
              <nb-card-header
                class="d-flex justify-content-between align-items-center section-nb-header"
              >
                <span> Region {{ regionIndex + 1 }}</span>
              </nb-card-header>
              <nb-card-body>
                <div class="row pl-3 pr-3 pb-3">
                  <div class="col-md-3">
                    <label [for]="'flightRegionId' + regionIndex" class="label"
                      >Flight Region</label
                    >
                    <nb-select
                      fullWidth
                      placeholder="Flight Region"
                      formControlName="flightRegionId"
                      [id]="'flightRegionId' + regionIndex"
                    >
                      <nb-option
                        *ngFor="let option of flightRegions"
                        (selectionChange)="onFlightRegionChangeHandler()"
                        (click)="
                          onFlightRegionAvailableChangeClickHandler(
                            option.id,
                            regionIndex
                          )
                        "
                        [value]="option.id"
                        [id]="'flightRegionId' + regionIndex"
                      >
                        {{ option.name }}
                      </nb-option>
                    </nb-select>
                  </div>
                </div>
                <!-- promotionDeals START-->
                <div class="col-md-12">
                  <nb-card  formArrayName="promotionDeals"
                    *ngFor="
                      let deal of promotionDeals(regionIndex).controls;
                      let promotionDealIndex = index
                    "
                  >
                    <div [formGroupName]="promotionDealIndex">
                      <nb-card-header
                        class="d-flex justify-content-between align-items-center"
                      >
                        <span
                          >Region {{ regionIndex + 1 }} | Deal
                          {{ promotionDealIndex + 1 }}</span
                        >
                      </nb-card-header>
                      <nb-card-body>
                        <div class="row p-2">
                          <div class="col-md-4">
                            <div class="form-group">
                              <label
                                class="label"
                                [for]="
                                  'flight-region' +
                                  regionIndex +
                                  'promotion-deal-fromDestinationsListId' +
                                  promotionDealIndex
                                "
                                >From</label
                              >

                              <nb-select
                              fullWidth
                              placeholder="From"
                              formControlName="fromDestinationsListId"
                              [id]="
                              'flight-region' +
                              regionIndex +
                              'promotion-deal-fromDestinationsListId' +
                              promotionDealIndex
                            "
                            >
                                 <nb-option
                                *ngFor="let option of originalDestinationList"
                                
                                (click)="
                                promotionDealDestinationListFromClickHandler(
                                  $event,
                                  regionIndex,
                                  promotionDealIndex
                                )
                              "
                                [value]="option.id"
                                [id]="
                                'flight-region' +
                                regionIndex +
                                'promotion-deal-fromDestinationsListId' +
                                promotionDealIndex
                              "
                              >
                                
                                <div class="d-flex flex-column">
                                  <div>
                                    {{ option.airportName }} -({{
                                      option.airportCode
                                    }})
                                  </div>
                                  <div>
                                    {{ option.cityName }}
                                    -{{ option.countryName }}
                                  </div>
                                </div>
                              </nb-option>
                            </nb-select>
                        
                            </div>
                          </div>
                          <div class="col-md-4">
                            <div class="form-group">
                              <label
                                class="label"
                                [for]="
                                  'flight-region' +
                                  regionIndex +
                                  'promotion-deal-toDestinationsListId' +
                                  promotionDealIndex
                                "
                                >To</label
                              >
                              <nb-select
                              fullWidth
                              placeholder="From"
                              formControlName="toDestinationsListId"
                              [id]="
                              'flight-region' +
                              regionIndex +
                              'promotion-deal-toDestinationsListId' +
                              promotionDealIndex
                            "
                            >
                              <nb-option
                                *ngFor="let option of originalDestinationList"
                                
                                (click)="
                                promotionDealDestinationListToClickHandler(
                                  $event,
                                  regionIndex,
                                  promotionDealIndex
                                )
                              "
                                [value]="option.id"
                                [id]="
                                'flight-region' +
                                regionIndex +
                                'promotion-deal-toDestinationsListId' +
                                promotionDealIndex
                              "
                              >
                                
                                <div class="d-flex flex-column">
                                  <div>
                                    {{ option.airportName }} -({{
                                      option.airportCode
                                    }})
                                  </div>
                                  <div>
                                    {{ option.cityName }}
                                    -{{ option.countryName }}
                                  </div>
                                </div>
                              </nb-option>
                              </nb-select>
                            </div>
                          </div>
                          </div>
                      </nb-card-body>
                      <nb-card-footer>
                        <div
                          class="row no-gutters my-3 justify-content-end w-100"
                        >
                          <div
                            class="pr-2"
                          >
                            <button
                              nbButton
                              class="new-btn"
                              status="primary"
                              (click)="AddPromotionDealHandler(regionIndex)"
                              size="small"
                            >
                              Add New Deal
                            </button>
                          </div>
                          <div *ngIf="promotionDeals(regionIndex).length > 1">
                          </div>
                        </div>
                      </nb-card-footer>
                    </div>
                  </nb-card>
                  <!-- formArrayName promotionDeals End -->
                </div>
              </nb-card-body>
            </div>
          </nb-card>

          <div class="row no-gutters justify-content-end w-100">
            <button nbButton nbStepperPrevious class="mr-2 prev-btn">
              prev
            </button>
          </div>
        </nb-step>
      </nb-stepper>
    </form>
  </nb-card-body>
</nb-card>

when we fetch data flight Region has 6 array and each region has 8 promotion deals
when we bind this using fetchPromotion(promotion)
Application is stacked and cannot do any thing

After i change to add data during when click NEXT button
it also take some time and when add new promotion deal it takes time to add new Deal view to user

Are there any ways to sort out this?

What is the recommended solution to run JS being part of an XHR request?

I already have read a lot of how to evaluate JS which gets loaded through XHR or Fetch API. Unfortunately, I’m still not able to determine what a good solution is meant to be in 2023.

As an example, I have a snippet of HTML which comes with an included JavaScript:

<div>
  <button>Click me</button>
  <script>
    document.currentScript.parentNode.addEventListener("click", _ => alert("there there"));
  </script>
</div>

So what I want is to not only place the HTML itself, which can easily be done using Node#replaceChild(), but also run the contained JavaScript.

Can anybody give a simple, clean and safe solution for this?

Copy data from multiple Excel files to one worksheet in Google Sheets – ExcejJS – how to avoid overwriting data?

First of all – I’m a rookie, not a developer.

I’m trying to copy data from multiple excel files, that are in one folder, to one worksheet in Google Sheets. I’m using excelJS and Google Sheets API. The issue is that despite I’m using “append” not “update” method, it overwrites the data. I assume it’s because the function is async. Is that the reason?

Here are parts of the code:

client.authorize(function (err, tokens) {
    if (err) {
        console.log(err);
        return;
    } else {
        console.log('Connected');
        gsrun();
        fs.readdir(folder, (err, files) => {
            files.forEach(file => {
                gsheetsUpload(file);
            });
        });
    };
});
function gsrun() {
    const clearOptions = {
        spreadsheetId: sID,
        range: 'Sheet1!A2:AB1000',
    };

    let resRemove = gsapi.spreadsheets.values.clear(clearOptions);
};
async function gsheetsUpload(f) {
    let filename = folder + f
    let wb = new Excel.Workbook();
    let excelFile = await wb.xlsx.readFile(filename);
    let ws = excelFile.getWorksheet('Some worksheet');
    let data = ws.getSheetValues();
    let prefix = ws.getCell('D6').value;
    let dataArray = [];

    data = data.map(function (r) {
        if (r[1] == 'Some cell value') {
            dataArray.push([r[2]]);
        };
    });

    const updateOptions = {
        spreadsheetId: sID,
        range: 'Sheet1!A2',
        valueInputOption: 'USER_ENTERED',
        resource: { values: dataArray }
    };

    console.log(dataArray);
    let resUpload = await gsapi.spreadsheets.values.append(updateOptions);
};

I read about Promises and tried using them. I’ve also tried setting timeout but that also didn’t help. How can I make the script wait for each iteration to end before the next one starts?

Ajax request receives HTML Page and not data JSON

The console.log in the “catch” is running because it receives html PAGE instead of json and I’don’t undertand why. Can you help me or or explain to me what I’m doing wrong.
Javascript:

 function upload_file() { 
                // Init        
                var frm_file_data = new FormData();
                frm_file_data.append('import', $("#import")[0].files[0]);
                // Enregistre
                return $.ajax({
                    method: 'POST',
                    url:    location.pathname.split('/').slice(-1)[0],
                    data:   {
                                action:         'get_file_data',
                                formData:        frm_file_data
                            },
                    processData: false,
                    contentType: false
                })  .done(function(res_data){
                    
                        try{
                            var data=JSON.parse(res_data);
                        }catch(e){                            
                            console.log(e); 
                            console.log(res_data);
                        }
                    })
            }

“cannot be used as a JSX Component” type error with dynamic imports in TypeScript and Next.js

In my Next.js application I import a component with dynamic import:

const SomeComponent = dynamic(
  () =>
    import(
      /* webpackChunkName: 'component-someComponent' */ './components/SomeComponent'
    )
);

and I get a TypeScript error when I’m trying to use it:

'SomeComponent' cannot be used as a JSX component.
  Its element type 'ReactElement<any, any> | Component<SomeComponentProps, any, any>' is not a valid JSX element.
    Type 'Component<SomeComponentProps, any, any>' is not assignable to type 'Element | ElementClass'.
      Type 'Component<SomeComponentProps, any, any>' is not assignable to type 'ElementClass'.
        The types returned by 'render()' are incompatible between these types.
          Type 'React.ReactNode' is not assignable to type 'import("/Users/test/app/node_modules/@types/react/index").ReactNode'.
            Type '{}' is not assignable to type 'ReactNode'.ts(2786)
const SomeComponent: ComponentType<SomeComponentProps>

I can silence the error by using paths in tsconfig.json:

    "paths": {
      "react": [ "./node_modules/@types/react" ],

but what would be the proper way to address this error?

CORS issue in Node.js Express application

I’m currently working on a Node.js Express backend with a React frontend, and I’m encountering CORS-related issues when attempting to make requests from my React app to the Express API.

Despite including the CORS middleware in my Express server, I’m still facing CORS issues. Are there additional configurations or steps I should take to ensure proper handling of CORS in this setup?

KonvaJS swaping node’s position not working as expected

I am working on a drag and drop project using Konva js and i want to be able to swap the position of 2 nodes when a node is drag onto another node.
In my code the swapping of the position works fine as i can click each node to console.log to see the position of the node has been swapped. But the position of the nodes after being updated is currently in the middle point of two nodes.

 nodeGroup.on("dragstart", function (evt) {
    if (evt.evt.ctrlKey) {
      stage.stopDrag();
      stage.startDrag();
      return;
    }
    //nodeGroup.moveToTop();
    const draggedNode = evt.target; // The node being drag
    draggedNode.zIndex(50); // set the drag node on top

    var targetRect = node.getClientRect();
    var nodeGroup = evt.currentTarget;
    oldColor = nodeGroup.children[0].attrs.fill;
    if (nodeGroup) {
      if (nodeGroup.children[0].attrs.fill === "red") return;
      nodeGroup.children[0].attrs.fill = "red";
    }
    //save the node's original position
    draggedNodeStartPosition = { x: nodeGroup.x(), y: nodeGroup.y() };
  });
  nodeGroup.on("dragend", function (evt) {
    if (!evt.evt) return;
    if (evt.evt.ctrlKey) {
      return;
    }

    var draggedNode = evt.currentTarget; // The node being drag
    var draggedRect = draggedNode.getClientRect(); // Dragged node 's bounding box
    var hasCollision = false;

    //check all of the nodes to find the node that is overlapping
    for (var n = 0; n < numberOfData; n++) {
      if (`node-${n}` !== draggedNode.id()) {
        // skip checking the node being drag
        const checkNode = stage.find(`#node-${n}`)[0]; // the node being colided or drag into
        const checkRect = checkNode.getClientRect();
        if (hasOverlap(draggedRect, checkRect)) {
          // Swap the positions of the dragged node and the collided node
          const draggedNodeOldPosition = draggedNodeStartPosition;
          const checkNodePosition = { x: checkNode.x(), y: checkNode.y() };

          draggedNode.position(checkNodePosition);
          //checkNode.position(draggedNodeOldPosition);

          // Optional: Update zindex properties if needed
          const draggedNodeZIndex = draggedNode.zIndex();
          draggedNode.zIndex(checkNode.zIndex());
          checkNode.zIndex(draggedNodeZIndex);

          hasCollision = true;
          break; // Exit the loop since we found a collision
        }
      }
    }
    draggedNode.getLayer().draw(); //reset layer

    // If there was no collision, update the old position
    if (!hasCollision) {
      draggedNode.position(draggedNodeStartPosition);
    }

    const targetRect = evt.target.getClientRect();
    nodeGroup.children[0].attrs.fill = oldColor;
    var target = stage.getIntersection(stage.getPointerPosition());
  });

I tried a number of methods including changing the position of only the node being drag, and it still moves the node to the middle point instead at the position of the node that is drag onto

codepen