Skip to content

Commit

Permalink
[Feat] Create video plugin module (#8613)
Browse files Browse the repository at this point in the history
* feat: adds video model and refactors imports

Introduces a new video model to support video functionalities.

This includes properties for video metadata, storage information, and relationships with other models like time slots and employees.  Additionally, several imports are reorganized for better code structure.

* feat: adds Video entity

This introduces the `Video` entity to store video-related information, including title, file path, recording date, duration, size, URL, storage provider, description, resolution, codec, frame rate, and uploader details.  It includes validation and relationships with `TimeSlot` and `Employee` entities.

* feat: introduces file storage path generation

This change introduces a new mechanism for generating file storage paths.  It uses a combination of date, tenant ID, and employee ID to create unique and organized storage locations.  A factory class simplifies the creation of storage engines with this path generation logic.

* feat(videos): adds DTOs for video management

Introduces Data Transfer Objects (DTOs) for creating, updating, and deleting videos.  Includes a FileDTO for handling video uploads and a BaseVideoDTO for common video properties.  These DTOs provide type safety and validation for video-related operations.

* feat: adds video repositories for MikroORM and TypeORM

Introduces `MikroOrmVideoRepository` and `TypeOrmVideoRepository` to support different ORM integrations.

* feat: adds video service

Introduces a new service to manage video entities. It utilizes both TypeORM and MikroORM repositories for data access.

* feat: add video entity and migration

This commit introduces the `Video` entity and its corresponding database migration.  The migration creates the `videos` table with fields for video metadata like title, file path, duration, size, storage provider, and relations to other entities such as tenant, organization, time slot, and uploading employee. It also includes indexes for efficient querying.

The migration handles different database types (PostgreSQL, SQLite, Better SQLite3, MySQL) and includes specific up and down migration logic for each.

* feat: adds commands and handlers for video management

This commit introduces new commands and handlers for managing videos:

- Creates `CreateVideoCommand` and `CreateVideoHandler` to add new videos.
- Implements `UpdateVideoCommand` and `UpdateVideoHandler` to modify existing videos.
- Adds `DeleteVideoCommand` and `DeleteVideoHandler` to remove videos.

This change enables basic CRUD operations for videos within the application.

* feat: adds queries and handlers for fetching videos

This introduces new queries and handlers for retrieving video data:

- `GetVideoQuery` and `GetVideoQueryHandler`: Fetch a single video by ID.
- `GetVideosQuery` and `GetVideosQueryHandler`: Fetch a list of videos with pagination support.

* feat: adds video subscriber for lifecycle management

Implements a TypeORM subscriber for the `Video` entity to manage file storage during entity lifecycle events.

- Sets the `fullUrl` property after loading a video entity by retrieving the URL from the configured storage provider.
- Deletes the associated video file from storage after a video entity is deleted.

This ensures consistent data and efficient storage management by automatically handling file operations related to videos.

* feat(videos): implements video controller

This commit introduces a new video controller feature, including:

- Creating new video records with associated metadata and file uploads.
- Retrieving video records by ID.
- Listing all video records with pagination support.
- Deleting video records.

The implementation uses CQRS and leverages a file storage service for managing video files.  It also includes validation and error handling for file uploads and data integrity.

* feat: Implements video plugin module

This commit introduces a new video plugin. It includes:

- A new module for videos with controllers, services, and repositories.
- Integration with TypeORM and MikroORM for database operations.
- CQRS implementation for handling commands and queries.
- Role-based permission management.
- Routing configuration for the plugin.

* feat: adds video entity and subscriber

Introduces the `Video` entity and its corresponding subscriber to the core module.  This lays the foundation for managing video data within the application.

* feat: adds PluginModule to AppModule

Registers the PluginModule in the application's root module to enable plugin functionality.

* fix: cspell spelling

* feat(plugin-video-capture): create library for video capture plugin

* refactor: plugin video capture module & entity

* fix(migration): video table for plugin video capture

* fix(videos): Implement query handlers for video CRUD operations

* fix(migration): refactor `video` [table] for MySQL

* refactor: suggestion by coderabbit AI

* fix(migration): refactor `video` [table] for DBs

* fix(subscriber):  video subscriber initialization and event handling

* fix(cspell): typo spelling :-)

---------

Co-authored-by: Rahul R. <rahulrathore576@gmail.com>
  • Loading branch information
adkif and rahul-rocket authored Dec 25, 2024
1 parent c0187af commit cfc5015
Show file tree
Hide file tree
Showing 60 changed files with 1,693 additions and 20 deletions.
12 changes: 11 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,17 @@
"xplatframework",
"localforage",
"longform",
"rfdc"
"rfdc",
"libx264",
"libx",
"WXGA",
"SXGA",
"UXGA",
"NTSC",
"libvpx",
"libaom",
"theora",
"Theora"
],
"useGitignore": true,
"ignorePaths": [
Expand Down
2 changes: 1 addition & 1 deletion apps/api/config/custom-webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ module.exports = composePlugins(
);

// Log for debugging
console.log('Copy Patterns:', packagePatterns);
// console.log('Copy Patterns:', packagePatterns);

// Log final config for debugging
// console.log('Final Webpack config:', JSON.stringify(config, null, 2));
Expand Down
1 change: 1 addition & 0 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"@gauzy/plugin-knowledge-base": "^0.1.0",
"@gauzy/plugin-product-reviews": "^0.1.0",
"@gauzy/plugin-sentry": "^0.1.0",
"@gauzy/plugin-video-capture": "^0.1.0",
"dotenv": "^16.0.3",
"yargs": "^17.5.0"
},
Expand Down
5 changes: 4 additions & 1 deletion apps/api/src/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { JobProposalPlugin } from '@gauzy/plugin-job-proposal';
import { JobSearchPlugin } from '@gauzy/plugin-job-search';
import { KnowledgeBasePlugin } from '@gauzy/plugin-knowledge-base';
import { ProductReviewsPlugin } from '@gauzy/plugin-product-reviews';
import { VideoCapturePlugin } from '@gauzy/plugin-video-capture';

import { SentryTracing as SentryPlugin } from './sentry';

Expand Down Expand Up @@ -50,5 +51,7 @@ export const plugins = [
// Indicates the inclusion or intention to use the KnowledgeBasePlugin in the codebase.
KnowledgeBasePlugin,
// Indicates the inclusion or intention to use the ProductReviewsPlugin in the codebase.
ProductReviewsPlugin
ProductReviewsPlugin,
// Indicates the inclusion or intention to use the VideoCapturePlugin in the codebase.
VideoCapturePlugin
];
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,9 @@
"build:package:plugins:pre": "yarn run build:package:ui-core && yarn run build:package:ui-auth && yarn run build:package:plugin:onboarding-ui && yarn run build:package:plugin:legal-ui && yarn run build:package:plugin:job-search-ui && yarn run build:package:plugin:job-matching-ui && yarn run build:package:plugin:job-employee-ui && yarn run build:package:plugin:job-proposal-ui && yarn run build:package:plugin:public-layout-ui && yarn run build:package:plugin:maintenance-ui && yarn run build:integration-ui-plugins",
"build:package:plugins:pre:prod": "yarn run build:package:ui-core:prod && yarn run build:package:ui-auth:prod && yarn run build:package:plugin:onboarding-ui:prod && yarn run build:package:plugin:legal-ui:prod && yarn run build:package:plugin:job-search-ui:prod && yarn run build:package:plugin:job-matching-ui:prod && yarn run build:package:plugin:job-employee-ui:prod && yarn run build:package:plugin:job-proposal-ui:prod && yarn run build:package:plugin:public-layout-ui:prod && yarn run build:package:plugin:maintenance-ui:prod && yarn run build:integration-ui-plugins:prod",
"build:package:plugins:pre:docker": "yarn run build:package:ui-core:docker && yarn run build:package:ui-auth:docker && yarn run build:package:plugin:onboarding-ui:docker && yarn run build:package:plugin:legal-ui:docker && yarn run build:package:plugin:job-search-ui:docker && yarn run build:package:plugin:job-matching-ui:docker && yarn run build:package:plugin:job-employee-ui:docker && yarn run build:package:plugin:job-proposal-ui:docker && yarn run build:package:plugin:public-layout-ui:docker && yarn run build:package:plugin:maintenance-ui:docker && yarn run build:integration-ui-plugins:docker",
"build:package:plugins:post": "yarn run build:package:plugin:integration-jira && yarn run build:package:plugin:integration-ai && yarn run build:package:plugin:sentry && yarn run build:package:plugin:jitsu-analytic && yarn run build:package:plugin:product-reviews && yarn run build:package:plugin:job-search && yarn run build:package:plugin:job-proposal && yarn run build:package:plugin:integration-github && yarn run build:package:plugin:knowledge-base && yarn run build:package:plugin:changelog && yarn run build:package:plugin:integration-hubstaff && yarn run build:package:plugin:integration-upwork",
"build:package:plugins:post:prod": "yarn run build:package:plugin:integration-jira:prod && yarn run build:package:plugin:integration-ai:prod && yarn run build:package:plugin:sentry:prod && yarn run build:package:plugin:jitsu-analytic:prod && yarn run build:package:plugin:product-reviews:prod && yarn run build:package:plugin:job-search:prod && yarn run build:package:plugin:job-proposal:prod && yarn run build:package:plugin:integration-github:prod && yarn run build:package:plugin:knowledge-base:prod && yarn run build:package:plugin:changelog:prod && yarn run build:package:plugin:integration-hubstaff:prod && yarn run build:package:plugin:integration-upwork:prod",
"build:package:plugins:post:docker": "yarn run build:package:plugin:integration-jira:docker && yarn run build:package:plugin:integration-ai:docker && yarn run build:package:plugin:sentry:docker && yarn run build:package:plugin:jitsu-analytic:docker && yarn run build:package:plugin:product-reviews:docker && yarn run build:package:plugin:job-search:docker && yarn run build:package:plugin:job-proposal:docker && yarn run build:package:plugin:integration-github:docker && yarn run build:package:plugin:knowledge-base:docker && yarn run build:package:plugin:changelog:docker && yarn run build:package:plugin:integration-hubstaff:docker && yarn run build:package:plugin:integration-upwork:docker",
"build:package:plugins:post": "yarn run build:package:plugin:integration-jira && yarn run build:package:plugin:integration-ai && yarn run build:package:plugin:sentry && yarn run build:package:plugin:jitsu-analytic && yarn run build:package:plugin:product-reviews && yarn run build:package:plugin:job-search && yarn run build:package:plugin:job-proposal && yarn run build:package:plugin:integration-github && yarn run build:package:plugin:knowledge-base && yarn run build:package:plugin:changelog && yarn run build:package:plugin:integration-hubstaff && yarn run build:package:plugin:integration-upwork && yarn run build:package:plugin:video-capture",
"build:package:plugins:post:prod": "yarn run build:package:plugin:integration-jira:prod && yarn run build:package:plugin:integration-ai:prod && yarn run build:package:plugin:sentry:prod && yarn run build:package:plugin:jitsu-analytic:prod && yarn run build:package:plugin:product-reviews:prod && yarn run build:package:plugin:job-search:prod && yarn run build:package:plugin:job-proposal:prod && yarn run build:package:plugin:integration-github:prod && yarn run build:package:plugin:knowledge-base:prod && yarn run build:package:plugin:changelog:prod && yarn run build:package:plugin:integration-hubstaff:prod && yarn run build:package:plugin:integration-upwork:prod && yarn run build:package:plugin:video-capture:prod",
"build:package:plugins:post:docker": "yarn run build:package:plugin:integration-jira:docker && yarn run build:package:plugin:integration-ai:docker && yarn run build:package:plugin:sentry:docker && yarn run build:package:plugin:jitsu-analytic:docker && yarn run build:package:plugin:product-reviews:docker && yarn run build:package:plugin:job-search:docker && yarn run build:package:plugin:job-proposal:docker && yarn run build:package:plugin:integration-github:docker && yarn run build:package:plugin:knowledge-base:docker && yarn run build:package:plugin:changelog:docker && yarn run build:package:plugin:integration-hubstaff:docker && yarn run build:package:plugin:integration-upwork:docker && yarn run build:package:plugin:video-capture:docker",
"build:package:plugin:integration-ai": "cross-env NODE_ENV=development NODE_OPTIONS=--max-old-space-size=12288 yarn nx build plugin-integration-ai",
"build:package:plugin:integration-ai:prod": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=12288 yarn nx build plugin-integration-ai",
"build:package:plugin:integration-ai:docker": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=60000 yarn nx build plugin-integration-ai",
Expand Down Expand Up @@ -231,6 +231,9 @@
"build:package:plugin:knowledge-base": "cross-env NODE_ENV=development NODE_OPTIONS=--max-old-space-size=12288 yarn nx build plugin-knowledge-base",
"build:package:plugin:knowledge-base:prod": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=12288 yarn nx build plugin-knowledge-base",
"build:package:plugin:knowledge-base:docker": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=60000 yarn nx build plugin-knowledge-base",
"build:package:plugin:video-capture": "cross-env NODE_ENV=development NODE_OPTIONS=--max-old-space-size=12288 yarn nx build plugin-video-capture",
"build:package:plugin:video-capture:prod": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=12288 yarn nx build plugin-video-capture",
"build:package:plugin:video-capture:docker": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=60000 yarn nx build plugin-video-capture",
"build:package:plugin:changelog": "cross-env NODE_ENV=development NODE_OPTIONS=--max-old-space-size=12288 yarn nx build plugin-changelog",
"build:package:plugin:changelog:prod": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=12288 yarn nx build plugin-changelog",
"build:package:plugin:changelog:docker": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=60000 yarn nx build plugin-changelog",
Expand Down Expand Up @@ -481,7 +484,7 @@
"husky": "^6.0.0",
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",
"jest-environment-node": "^29.4.1",
"jest-environment-node": "^29.7.0",
"jest-jasmine2": "29.7.0",
"jest-preset-angular": "14.1.1",
"jsonc-eslint-parser": "^2.1.0",
Expand Down
21 changes: 10 additions & 11 deletions packages/contracts/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
export * from './lib/accounting-template.model';
/** App Setting Model */
export * from './lib/activity-log.model';
export * from './lib/activity-watch.model';
export * from './lib/api-call-log.model';
export * from './lib/app.model';
export * from './lib/appointment-employees.model';
Expand All @@ -29,6 +30,7 @@ export * from './lib/core.model';
export * from './lib/country.model';
export * from './lib/currency.model';
export * from './lib/custom-smtp.model';
export * from './lib/daily-plan.model';
export * from './lib/date-picker.model';
export * from './lib/dashboard.model';
export * from './lib/deal.model';
Expand All @@ -51,7 +53,6 @@ export * from './lib/equipment.model';
export * from './lib/estimate-email.model';
export * from './lib/event-type.model';
export * from './lib/expense-category.model';
export * from './lib/expense-category.model';
export * from './lib/expense.model';
export * from './lib/favorite.model';
export * from './lib/feature.model';
Expand All @@ -67,8 +68,8 @@ export * from './lib/hubstaff.model';
export * from './lib/image-asset.model';
export * from './lib/import-export.model';
export * from './lib/income.model';
export * from './lib/integration.model';
export * from './lib/integration-setting.model';
export * from './lib/integration.model';
export * from './lib/invite.model';
export * from './lib/invoice-estimate-history.model';
export * from './lib/invoice-item.model';
Expand All @@ -87,8 +88,8 @@ export * from './lib/organization-employment-type.model';
export * from './lib/organization-expense-category.model';
export * from './lib/organization-language.model';
export * from './lib/organization-positions.model';
export * from './lib/organization-projects.model';
export * from './lib/organization-project-module.model';
export * from './lib/organization-projects.model';
export * from './lib/organization-recurring-expense.model';
export * from './lib/organization-sprint.model';
export * from './lib/organization-task-setting.model';
Expand All @@ -113,6 +114,7 @@ export * from './lib/request-approval.model';
export * from './lib/resource-link.model';
export * from './lib/role-permission.model';
export * from './lib/role.model';
export * from './lib/screening-task.model';
export * from './lib/screenshot.model';
export * from './lib/seed.model';
export * from './lib/shared-types';
Expand All @@ -130,8 +132,6 @@ export * from './lib/task-status.model';
export * from './lib/task-version.model';
export * from './lib/task-view.model';
export * from './lib/task.model';
export * from './lib/daily-plan.model';
export * from './lib/screening-task.model';
export * from './lib/tenant.model';
export * from './lib/time-off.model';
export * from './lib/timesheet-statistics.model';
Expand All @@ -142,18 +142,17 @@ export * from './lib/upwork.model';
export * from './lib/user-organization.model';
export * from './lib/user.model';
export * from './lib/wakatime.model';
export * from './lib/activity-watch.model';

export {
ActorTypeEnum,
BaseEntityEnum,
IBaseEntityModel as BaseEntityModel,
ID,
IBasePerTenantAndOrganizationEntityModel,
IBasePerTenantEntityModel,
IBaseSoftDeleteEntityModel,
IBaseRelationsEntityModel,
ActorTypeEnum,
JsonData,
BaseEntityEnum
IBaseSoftDeleteEntityModel,
ID,
JsonData
} from './lib/base-entity.model';

export * from './lib/proxy.model';
2 changes: 2 additions & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export {
export * from './lib/logger';
export * from './lib/core';
export * from './lib/core/seeds';
export { LazyFileInterceptor } from './lib/core/interceptors';
export { FileStorage, FileStorageFactory, UploadedFileStorage } from './lib/core/file-storage';
export * from './lib/shared';
export * from './lib/event-bus';

Expand Down
1 change: 1 addition & 0 deletions packages/core/src/lib/core/entities/subscribers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import {
} from '../internal';
import { TenantOrganizationBaseEntityEventSubscriber } from './tenant-organization-base-entity.subscriber';

// Get the ORM type from the MultiORMEnum
const ormType = getORMType();

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface IDirectoryPathGenerator {
getBaseDirectory(name: string): string;
getSubDirectory(): string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Concrete implementation of the path generator
import * as moment from 'moment';
import * as path from 'path';
import { v4 as uuid } from 'uuid';
import { RequestContext } from '../../context';
import { IDirectoryPathGenerator } from './directory-path-generator.interface';

export class DirectoryPathGenerator implements IDirectoryPathGenerator {
/**
* Generates the base directory path with the given name.
* Includes a timestamped subdirectory in the format `YYYY/MM/DD`.
*
* @param name - The name to be used as the base directory.
* @returns The full base directory path including the timestamped subdirectory.
*/
public getBaseDirectory(name: string): string {
return path.join(name, moment().format('YYYY/MM/DD'));
}

/**
* Generates a subdirectory path specific to the current user context.
* Uses the `tenantId` and `employeeId` from the current user, or generates UUIDs if not available.
*
* @returns The subdirectory path in the format `<tenantId>/<employeeId>`.
*/
public getSubDirectory(): string {
// Retrieve the current user from the request context
const user = RequestContext.currentUser();

// Extract or generate identifiers for the tenant and employee
const tenantId = user?.tenantId || uuid(); // Use the tenantId if available, otherwise generate a UUID
const employeeId = user?.employeeId || uuid(); // Use the employeeId if available, otherwise generate a UUID

// Construct and return the subdirectory path
return path.join(tenantId, employeeId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import multer from 'multer';
import * as path from 'path';
import { FileStorage } from '../file-storage';
import { DirectoryPathGenerator } from './directory-path-generator';
import { IDirectoryPathGenerator } from './directory-path-generator.interface';

// FileStorageFactory
export class FileStorageFactory {
private static readonly pathGenerator: IDirectoryPathGenerator = new DirectoryPathGenerator();

public static create(baseDirname: string): multer.StorageEngine {
const baseDirectory = this.pathGenerator.getBaseDirectory(baseDirname);
const subDirectory = this.pathGenerator.getSubDirectory();

return new FileStorage().storage({
dest: () => path.join(baseDirectory, subDirectory),
prefix: baseDirname
});
}
}
3 changes: 3 additions & 0 deletions packages/core/src/lib/core/file-storage/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './directory-path-generator';
export * from './directory-path-generator.interface';
export * from './file-storage-factory';
1 change: 1 addition & 0 deletions packages/core/src/lib/core/file-storage/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './file-storage';
export * from './file-storage.module';
export * from './helpers';
export * from './tenant-settings.middleware';
export * from './uploaded-file-storage';
2 changes: 1 addition & 1 deletion packages/core/src/lib/core/interceptors/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export * from './cloud-migrate.interceptor';
export * from './serializer.interceptor';
export * from './lazy-file-interceptor';
export * from './transform.interceptor';
export * from './transform.interceptor';
Loading

0 comments on commit cfc5015

Please sign in to comment.