November 18, 2024
November 18, 2024
ABP - Open source web application framework
If you are considering a framework for the .NET and the ASP.NET Core platforms, ABP Framework is an ideal candidate. It streamlines development, improves productivity, and ensures a consistent experience for building modern web solutions. The ABP Framework offers several compelling reasons for its adoption, let's explore…
November 15, 2024
DICOM Services
Following the post "Overview of DICOM Image", this time I’ll introduce DICOM Services, which are used to store and share medical images between different systems.
November 15, 2024
How to use the Laravel Vite plugin
Introduce the Laravel Vite plugin
Laravel Vite is an integration tool that brings the benefits of Vite to Laravel applications. Vite is a cutting-edge build tool designed to enhance the development workflow by offering rapid build times and efficient handling of front-end assets. Unlike older bundlers such as Webpack, Vite uses a modern approach that allows for quick updates and seamless development with contemporary JavaScript frameworks. This results in a more streamlined and productive experience when managing assets and building applications.
In this blog, Vue is the framework chosen, which provides a flexible and progressive approach to building user interfaces. It offers a lightweight core with an ecosystem of libraries and tools, making it ideal for small-scale and large-scale projects. The reactive data binding and component-based architecture make it particularly effective for developing dynamic, interactive applications.
Benefits of Using Vite
Vite is a game-changing tool built specifically for modern front-end development. It’s optimized for frameworks like Vue, React, and other JavaScript-based ecosystems, offering a range of features that set it apart from older solutions. Here’s why Vite is a standout choice for modern web development:
-
Fast Development Server: Vite starts quickly, even for large projects, by using ES Modules directly in the browser, skipping the bundling process for faster local development.
-
Quick Hot Module Replacement (HMR): Vite provides instant updates in the browser without refreshing, making it ideal for real-time UI feedback in frameworks like Vue and React.
-
Efficient Production Builds with Rollup: For production, Vite uses Rollup to create small, optimized builds with features like tree-shaking and module splitting.
-
Built-in Framework Support: Vite supports Vue, React, TypeScript, and has plugins for additional frameworks like Svelte and Preact .
- Full ESM Compatibility: By leveraging native ES Modules, Vite skips transpiling in development, leading to faster load times.
-
Rich Plugin Ecosystem: Vite supports rollup and custom plugins, allowing features like JSX support and environment management.
-
Modern JS and CSS Support: Vite manages CSS modules, preprocessors, and assets like images and fonts effectively.
-
Future-Ready Platform: Built for modern standards like HTTP/2 and ESM, Vite is equipped for the next generation of JavaScript applications.
How to use Laravel with Vite
First, we create the new project with the command, please choose name of the project. In the blog, laravel-mix-vue was chosen because it points to the combination of Laravel and Vue.js with the support of Vite, bringing the assets of Vue.js after the bundling process to Laravel:
composer create-project laravel/laravel laravel-mix-vue
Composer is a dependency manager specifically designed for PHP. Composer handles libraries and packages in PHP projects, allowing developers to define and manage the libraries or frameworks they need in a project. If you have not installed Composer on your local machine, please refer to https://getcomposer.org/download/ for instructions.
Then navigate to the folder container of the project and run the commands below to install dependencies and start it:
yarn
yarn dev

After completing all task to set up the project, you can install Vue JS and write an example component.
yarn add vue --dev
yarn add @vitejs/plugin-vue --dev
In Yarn, the --dev flag is used to add packages specifically for development purposes. When you use --dev, Yarn installs the package as a development dependency, meaning it’s only needed during development and not in production.
Create the new file for the first component Vue js (resources/js/components/ComponentExample.vue) like the following code
This structure includes:
- <script>: Where you can define the component’s name, data, and methods.
- <template>: The actual HTML structure rendered by the component.

Open up resources/app.js and update its refer code below.
- createApp: This is a method used to create a new Vue app instance. It takes an options object that defines the behavior of the app.
- mount: This method attaches the Vue app to an element in the DOM with the id="app". This is where the app will be rendered.
- components: Components are the fundamental building blocks in Vue.js. They encapsulate their own logic, template, and styles, making them reusable and modular.

Open the file vite.config.js to define the Vue plugin.
plugins: [ ... ]:
- This section defines the list of plugins to use in the Vite build process.
- The Laravel plugin is responsible for managing the entry points (e.g., app.css, app.js) and enabling the automatic injection of Vite-generated assets into Blade views.
- The Vue plugin is responsible for enabling Vue.js component processing. The template configuration inside the Vue plugin allows customization of how asset URLs are transformed in Vue templates.
transformAssetUrls:
- The configuration inside Vue allows controlling how URLs in Vue component templates are processed. Setting base: null avoids adding a base path to URLs, and includeAbsolute: false prevents absolute URLs from being transformed.
resolve: { alias: { vue: 'vue/dist/vue.esm-bundler.js' } }
- This defines an alias for the Vue package to ensure that the correct version of Vue is used with Vite (specifically, the Vue 3 build that supports the bundler).

Finally, you need to modify the template in resources/views/welcome.blade.php.
Use the following commands to build and run your application:
- yarn build to compile the assets.
- php artisan serve to run your application.
The yarn build command compiles and bundles your Vue.js code, transforming it into optimized JavaScript and CSS files. These files will be placed in the public directory, where Laravel can access them. This process is managed by Laravel, which uses Vite to bundle and version the assets. Versioning ensures that the most up-to-date assets are served to users, preventing caching issues.
The command php artisan serve starts a local development server, typically accessible at http://127.0.0.1:8000/. This server will handle requests to your Laravel backend and serve your Blade templates along with the compiled Vue.js frontend assets.

The component should now be rendered tag H2 with content IVC.

Reference
https://laravel.com/docs/11.x/vite
(Cover image)
November 14, 2024
Common Errors and Handling Errors in JavaScript
When you write JavaScript, you'll run into errors. The trick is to know how to deal with them and use debugging tools to find out why they happen. This guide will help you grasp error handling, use good debugging methods, and show you some real examples.
November 13, 2024
Development an object detection Flutter application with Google ML Toolkit
Overview
Prerequisites
- Flutter installed.
- Basic knowledge of Flutter and Dart.
- An Android or iOS device for testing (emulators might not support camera features, the source code below is just tested on Android device).
1. Set Up Your Flutter Project
simple_object_detection_app:flutter create simple_object_detection_appdependencies:flutter:sdk: fluttercamera: ^0.10.5+9google_mlkit_object_detection: ^0.13.0google_mlkit_commonss: ^0.7.0
flutter pub get2. Configure Android Permissions
<usess-feature androidd:name="android.hardwaree.camera" android:required="false"/><uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.INTERNET" />3. Create the UI in Flutter
import 'dart:io';
import 'package:flutter/material.dart';import 'package:camera/camera.dart';import 'package:google_mlkit_object_detection/google_mlkit_object_detection.dart';void main() async {WidgetsFlutterBinding.ensureInitialized();final cameraList = await availableCameras();runApp(SODAApp(camera: cameraList.first));}
class SODAApp extends StatelessWidget {final CameraDescription camera;const SODAApp({super.key, required this.camera});
@overrideWidget build(BuildContext context) {return MaterialApp(home: DetectionScreen(camera: camera),);}}
class DetectionScreen extends StatefulWidget {final CameraDescription camera;const DetectionScreen({super.key, required this.camera});@overrideDetectionScreenState createState() => DetectionScreenState();}
class DetectionScreenState extends State<DetectionScreen> {late CameraController _controller;late ObjectDetector _objectDetector;bool _isDetecting = false;List<DetectedObject> _detectedObjects = [];
@overridevoid initState() {super.initState();_initializeCamera();_initializeObjectDetector();}
void _initializeCamera() {_controller = CameraController(widget.camera, ResolutionPreset.medium,enableAudio: false,imageFormatGroup: Platform.isAndroid ? ImageFormatGroup.nv21 : ImageFormatGroup.bgra8888);_controller.initialize().then((_) {if (!mounted) return;setState(() {});_controller.startImageStream(_processCameraImage);});}void _initializeObjectDetector() {final options = ObjectDetectorOptions(mode: DetectionMode.stream,classifyObjects: true,multipleObjects: true
);_objectDetector = ObjectDetector(options: options);}
void _processCameraImage(CameraImage image) async {if (_isDetecting ) return;_isDetecting = true;
final inputImage = _convertToInputImage(image);final objects = await _objectDetector.processImage(inputImage);setState(() {_detectedObjects = objects;});_isDetecting = false;}
InputImage _convertToInputImage(CameraImage image) {var sensorOrientation = widget.camera.sensorOrientation;InputImageRotation? rotation;if (Platform.isIOS) {rotation = InputImageRotationValue.fromRawValue(sensorOrientation);} else if (Platform.isAndroid) {var rotationCompensation = 0;if (widget.camera.lensDirection == CameraLensDirection.front) {rotationCompensation = (sensorOrientation + rotationCompensation) % 360;} else {rotationCompensation =(sensorOrientation - rotationCompensation + 360) % 360;}rotation = InputImageRotationValue.fromRawValue(rotationCompensation);}final format = InputImageFormatValue.fromRawValue(image.format.raw) ??InputImageFormat.nv21;final plane = image.planes.first;return InputImage.fromBytes(bytes: plane.bytes,metadata: InputImageMetadata(size: Size(image.width.toDouble(), image.height.toDouble()),rotation: rotation!,format: format,bytesPerRow: plane.bytesPerRow,),);}
@overridevoid dispose() {_controller.dispose();_objectDetector.close();super.dispose();}
@overrideWidget build(BuildContext context) {if (!_controller.value.isInitialized) {return Scaffold(appBar: AppBar(title: const Text('Object Detection')),body: const Center(child: CircularProgressIndicator()),);}
return Scaffold(appBar: AppBar(title: const Text('Object Detection')),body: Stack(children: [CameraPreview(_controller),_buildBoundingBoxes(),],),);}Widget _buildBoundingBoxes() {return CustomPaint(painter: BoxPainter(objects: _detectedObjects),);}}
class BoxPainter extends CustomPainter {final List<DetectedObject> objects;BoxPainter({required this.objects});@overridevoid paint(Canvas canvas, Size size) {final paint = Paint()..color = Colors.red..style = PaintingStyle.stroke..strokeWidth = 2.0;for (var object in objects) {final rect = object.boundingBox;canvas.drawRect(Rect.fromLTRB(rect.left,rect.top,rect.right,rect.bottom,),paint,);TextStyle textStyle = const TextStyle(color: Colors.purpleAccent,fontSize: 16,fontWeight: FontWeight.bold,);TextSpan textSpan = TextSpan(text: object.labels.isEmpty ? 'No name':object.labels.first.text,style: textStyle,);TextPainter textPainter = TextPainter(text: textSpan,textDirection: TextDirection.ltr,textAlign: TextAlign.center,);textPainter.layout();double dx = rect.left + (rect.width - textPainter.width) / 2;double dy = rect.top + (rect.height - textPainter.height) / 2;Offset offset = Offset(dx, dy);textPainter.paint(canvas, offset);}}@overridebool shouldRepaint(covariant CustomPainter oldDelegate) => true;}Explanation
_objectDetector.processImage(inputImage)
Testing the App
flutter run
Troubleshooting
ResolutionPreset.low.Conclusion
(Feature image is come from Freepik)
November 6, 2024
Understanding Vector Databases: What, How, and Why They Matter in AI
Understanding Vector Databases: What, How, and Why They Matter in AI
If you've been exploring the world of artificial intelligence (AI), you might have come across the term "vector database." This concept is gaining traction, especially with applications like image recognition, natural language processing, and recommendation systems. But what exactly is a vector database, and why is it so valuable in these contexts? In this blog post, we'll dive into what a vector database is, how it works, and why you should consider using it for your AI projects.
October 28, 2024
End-to-End Automation Testing for Modern Web Applications Using the Playwright API in TypeScript.
What is testing, and what are the advantages of test automation?
Testing is a crucial process in the software development lifecycle. It ensures the software meets the required quality standards before being released to end users. Testing can be conducted in various environments, such as local, staging, and production, each serving a specific purpose in the development pipeline.
Automated testing offers advantages over manual testing. It improves efficiency by executing tests quickly and consistently, allows for the reuse of test scripts, and extends the coverage of testing. Although the initial investment in automation may be high, the long-term benefits include reduced testing time, cost savings, and better integration with continuous development processes. Embracing automated testing can lead to more reliable software, shorter release cycles, and an optimized development process.
What is Playwright API?
Playwright is a framework for Web Testing and Automation. It allows testing cross-browser and cross-platform. It provides strong features and powerful tools.
How to use it?
In this article, we will concentrate on one specific feature of the web application for testing automation.
The first is installing the playwright with yarn or npm by CLI. You can also install it via the Visual Studio Code extension store.
yarn create playwright

Assume that we have 1 test case for the web https://isb-vietnam.net/
Test case: Verify Visibility of Tech Link After Clicking Blog
Description: This test case verifies that after navigating to the website and clicking on the "Blog" link, the "Tech" link becomes visible. It also captures a screenshot of the "Tech" link.
Preconditions:
- Ensure the Playwright testing environment is set up correctly.
- The website https://isb-vietnam.net/ is accessible.
Test Steps:
- Navigate to the Website:
-
- URL: https://isb-vietnam.net/
- Action: Open the website in a browser.
- Click on the First Blog Link:
-
- Locator: Role link with name Blog
- Action: Click on the first instance of the Blog link.
- Verify the Visibility of the Tech Link:
-
- Locator: Role link with name Tech
- Assertion: Check that the first instance of the Tech link is visible on the page.
- Capture Screenshot of Tech Link:
-
- Path: tech-link.png
- Action: Take a screenshot of the Tech link element.
Expected Results:
- The "Tech" link should be visible on the page after clicking the "Blog" link.
- The screenshot file tech-link.png should be saved in the working directory, containing the Tech link.
This is the automation code referred to in the test case above.

Now, we can run a test with command:
yarn playwright test

By default, tests will be run on all 3 browsers, chromium, firefox, and webkit using 3 workers.
Then completing the test, an HTML report is generated. To review it with the command below:
yarn playwright show-report

Alternatively, the image of the Tech link is captured screenshot.

Conclusion
Playwright is a powerful and versatile testing framework that significantly enhances the process of web application testing. It supports multiple browsers and provides advanced features like auto-waiting and parallel test execution. When integrated with TypeScript, Playwright can leverage TypeScript's strong typing and modern features to streamline the development and testing process, making it easier to catch errors early and maintain high code quality.
Reference
September 13, 2024
Integrating Bloc with MVVM in Flutter
class User { final String name; final int age; User({required this.name, required this.age}); }import 'package:bloc/bloc.dart'; // Events abstract class UserEvent {} class LoadUser extends UserEvent {} // States abstract class UserState {} class UserInitial extends UserState {} class UserLoaded extends UserState { final User user; UserLoaded(this.user); } // Bloc class UserBloc extends Bloc<UserEvent, UserState> { UserBloc() : super(UserInitial()) { on<LoadUser>((event, emit) { // Simulate to fetch the user data (from a repository) final user = User(name: "Teddy Nguyen", age: 44); //Emit the new event emit(UserLoaded(user)); }); } } import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class UserScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('User')), body: BlocBuilder<UserBloc, UserState>( builder: (context, state) { if (state is UserInitial) { return Center(child: CircularProgressIndicator()); } else if (state is UserLoaded) { return Center(child: Text('Name: ${state.user.name}, Age: ${state.user.age}')); } else { return Center(child: Text('Something went wrong!')); } }, ), ); } }