Skip to content

Commit

Permalink
[759]Create webhook
Browse files Browse the repository at this point in the history
  • Loading branch information
thinhpham-nashtech committed Aug 2, 2024
1 parent 642cc92 commit c6df056
Show file tree
Hide file tree
Showing 81 changed files with 2,461 additions and 4 deletions.
58 changes: 58 additions & 0 deletions .github/workflows/webhook-ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: webhook service ci

on:
push:
branches: ["main"]
paths:
- "webhook/**"
- ".github/workflows/actions/action.yaml"
- ".github/workflows/webhook-ci.yaml"
pull_request:
branches: ["main"]
paths:
- "webhook/**"
- ".github/workflows/actions/action.yaml"
- ".github/workflows/webhook-ci.yaml"

workflow_dispatch:

jobs:
Build:
runs-on: ubuntu-latest
env:
FROM_ORIGINAL_REPOSITORY: ${{ github.event.pull_request.head.repo.full_name == github.repository || github.ref == 'refs/heads/main' }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- uses: ./.github/workflows/actions
- name: Run Maven Build Command
run: mvn clean install -DskipTests -f webhook
- name: Run Maven Test
run: mvn test -f webhook
- name: Unit Test Results
uses: dorny/test-reporter@v1
if: ${{ env.FROM_ORIGINAL_REPOSITORY == 'true' && (success() || failure()) }}
with:
name: Webhook-Service-Unit-Test-Results
path: "webhook/**/surefire-reports/*.xml"
reporter: java-junit
- name: Analyze with sonar cloud
if: ${{ env.FROM_ORIGINAL_REPOSITORY == 'true' }}
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: mvn org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -f webhook
- name: Log in to the Container registry
if: ${{ github.ref == 'refs/heads/main' }}
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker images
if: ${{ github.ref == 'refs/heads/main' }}
uses: docker/build-push-action@v6
with:
context: ./webhook
push: true
tags: ghcr.io/nashtech-garage/yas-webhook:latest
8 changes: 8 additions & 0 deletions backoffice-bff/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ spring:
cloud:
gateway:
routes:
- id: api_webhook_local
uri: http://localhost:8092
#uri: http://api.yas.local
predicates:
- Path=/api/webhook/**
filters:
- RewritePath=/api/(?<segment>.*), /$\{segment}
- TokenRelay=
- id: api_product_local
uri: http://localhost:8080
#uri: http://api.yas.local
Expand Down
6 changes: 6 additions & 0 deletions backoffice/asset/data/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
SALES_SHOPPING_CARTS_AND_WISHLISTS_URL,
SYSTEM_PAYMENT_PROVIDERS,
SYSTEM_SETTINGS,
WEBHOOKS_URL
} from '@constants/Common';

export const menu_catalog_item_data = [
Expand Down Expand Up @@ -155,4 +156,9 @@ export const menu_system_item_data = [
name: 'Settings',
link: SYSTEM_SETTINGS,
},
{
id: 3,
name: 'Webhooks',
link: WEBHOOKS_URL,
}
];
2 changes: 1 addition & 1 deletion backoffice/common/components/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ const Sidebar = (menu: MenuProps) => {
</ul>
</li>

<li className={menuActive == 'sales' ? 'active' : ''} onClick={() => changeMenu('system')}>
<li className={menuActive == 'system' ? 'active' : ''} onClick={() => changeMenu('system')}>
<Link
href="#systemSubmenu"
data-target="#systemSubmenu"
Expand Down
1 change: 1 addition & 0 deletions backoffice/constants/Common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const SALES_SHOPPING_CARTS_AND_WISHLISTS_URL = '/sales/shopping-carts-and

export const SYSTEM_PAYMENT_PROVIDERS = '/system/payment-providers';
export const SYSTEM_SETTINGS = '/system/settings';
export const WEBHOOKS_URL = '/webhook';

export const DEFAULT_PAGE_SIZE = 10;
export const DEFAULT_PAGE_NUMBER = 0;
Expand Down
84 changes: 84 additions & 0 deletions backoffice/modules/webhook/components/EventInformation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { useEffect, useState } from 'react';
import { UseFormGetValues, UseFormSetValue } from 'react-hook-form';

import { WebhookEvent } from '@webhookModels/Event';
import { Webhook } from '@webhookModels/Webhook';
import { getEvents } from '@webhookServices/EventService';

type Props = {
events?: WebhookEvent[];
setValue: UseFormSetValue<Webhook>;
getValue: UseFormGetValues<Webhook>;
};

const EventInformation = ({ events, setValue, getValue: _getValue }: Props) => {
const [allEvents, setAllEvents] = useState<WebhookEvent[]>([]);
let [latestCheckedEvent, setLatestCheckedEvent] = useState<WebhookEvent[]>([]);
let listCheckEvent: WebhookEvent[] = [];

useEffect(() => {
getEvents().then((data) => {
setAllEvents(data);
if (events !== undefined && latestCheckedEvent.length === 0) {
events.map((item: any) => {
latestCheckedEvent.push(item);
});
setLatestCheckedEvent(latestCheckedEvent);
}
});
}, []);

function checkedTrue(id: number) {
const found = latestCheckedEvent.find((element) => element.id === id);
if (found === undefined) return false;
return true;
}

const onUpdateCheckedEvent = (e: any) => {
const checkedEventId = Number(e.target.value);
if (e.target.checked) {
const webhookEvent = allEvents.find((element) => element.id === checkedEventId);
if (webhookEvent !== undefined) {
setLatestCheckedEvent([webhookEvent, ...latestCheckedEvent]);
latestCheckedEvent = [webhookEvent, ...latestCheckedEvent];
}
} else {
latestCheckedEvent = latestCheckedEvent.filter((item) => item.id !== checkedEventId);
setLatestCheckedEvent(latestCheckedEvent);
}
setValue('events', latestCheckedEvent);
};

return (
<div className="choice-event">
<ul style={{ listStyleType: 'none' }}>
{allEvents.map((event, index) => (
<li key={event.id}>
<input
value={event.id || ''}
type="checkbox"
name="event"
checked={checkedTrue(event.id) === true ? true : false}
id={`checkbox-${event.id}`}
onChange={onUpdateCheckedEvent}
/>
<label
htmlFor={`checkbox-${event.id}`}
style={{
paddingLeft: '15px',
fontSize: '1rem',
paddingTop: '10px',
paddingBottom: '5px',
}}
>
{' '}
{event.name}
</label>
</li>
))}
</ul>
</div>
);
};

export default EventInformation;
47 changes: 47 additions & 0 deletions backoffice/modules/webhook/components/WebhookInformation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { FieldErrorsImpl, UseFormRegister, UseFormSetValue, UseFormTrigger } from 'react-hook-form';
import { CheckBox } from 'common/items/Input';
import { Input } from 'common/items/Input';
import { Webhook } from '../models/Webhook';
import { ContentType } from '@webhookModels/ContentType';

type Props = {
register: UseFormRegister<Webhook>;
errors: FieldErrorsImpl<Webhook>;
setValue: UseFormSetValue<Webhook>;
trigger: UseFormTrigger<Webhook>;
webhook?: Webhook;
};

const WebhookInformation = ({ register, errors, setValue, trigger, webhook }: Props) => {

return (
<>
<Input
labelText="Payload URL"
field="payloadUrl"
defaultValue={webhook?.payloadUrl}
register={register}
registerOptions={{
required: { value: true, message: 'Payload URL is required' },
}}
error={errors.payloadUrl?.message}
/>
<Input
labelText="Content Type"
field="contentType"
defaultValue={ContentType.APPLICATION_JSON}
register={register}
disabled={true}
/>
<Input labelText="Secret" field="secret" defaultValue={webhook?.secret} register={register} />
<CheckBox
labelText="Active"
field="isActive"
register={register}
defaultChecked={webhook?.isActive}
/>
</>
);
};

export default WebhookInformation;
3 changes: 3 additions & 0 deletions backoffice/modules/webhook/models/ContentType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export enum ContentType {
APPLICATION_JSON = 'application/json'
}
4 changes: 4 additions & 0 deletions backoffice/modules/webhook/models/Event.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export type WebhookEvent = {
id: number;
name: string;
};
10 changes: 10 additions & 0 deletions backoffice/modules/webhook/models/Webhook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { WebhookEvent } from "./Event";

export type Webhook = {
id: number;
payloadUrl: string;
secret: string;
contentType: string;
isActive: boolean;
events: WebhookEvent[];
};
7 changes: 7 additions & 0 deletions backoffice/modules/webhook/services/EventService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { WebhookEvent } from '../models/Event';


export async function getEvents(): Promise<WebhookEvent[]> {
const response = await fetch('/api/webhook/backoffice/events');
return await response.json();
}
38 changes: 38 additions & 0 deletions backoffice/modules/webhook/services/WebhookService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Webhook } from '../models/Webhook';

export async function getWebhooks(pageNo: number, pageSize: number) {
const url = `/api/webhook/backoffice/webhooks/paging?pageNo=${pageNo}&pageSize=${pageSize}`;
const response = await fetch(url);
return await response.json();
}

export async function getWebhook(id: number): Promise<Webhook> {
const response = await fetch('/api/webhook/backoffice/webhooks/' + id);
return await response.json();
}

export async function createWebhook(webhook: Webhook) {
const response = await fetch('/api/webhook/backoffice/webhooks', {
method: 'POST',
body: JSON.stringify(webhook),
headers: { 'Content-type': 'application/json; charset=UTF-8' },
});
return response;
}
export async function updateWebhook(id: number, webhook: Webhook) {
const response = await fetch('/api/webhook/backoffice/webhooks/' + id, {
method: 'PUT',
body: JSON.stringify(webhook),
headers: { 'Content-type': 'application/json; charset=UTF-8' },
});
if (response.status === 204) return response;
else return await response.json();
}
export async function deleteWebhook(id: number) {
const response = await fetch('/api/webhook/backoffice/webhooks/' + id, {
method: 'DELETE',
headers: { 'Content-type': 'application/json; charset=UTF-8' },
});
if (response.status === 204) return response;
else return await response.json();
}
Loading

0 comments on commit c6df056

Please sign in to comment.