Metamigo -> Bridge
This commit is contained in:
parent
242f3cf6b8
commit
a445762a37
145 changed files with 396 additions and 16668 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -19,7 +19,7 @@ docker-compose.yml
|
||||||
coverage
|
coverage
|
||||||
.pgpass
|
.pgpass
|
||||||
**/dist/**
|
**/dist/**
|
||||||
.metamigo.local.json
|
.bridge.local.json
|
||||||
out/
|
out/
|
||||||
signald-state/*
|
signald-state/*
|
||||||
!./signald-state/.gitkeep
|
!./signald-state/.gitkeep
|
||||||
|
|
|
||||||
|
|
@ -84,16 +84,16 @@ leafcutter-docker-release:
|
||||||
variables:
|
variables:
|
||||||
DOCKER_NS: ${CI_REGISTRY}/digiresilience/link/link-stack/leafcutter
|
DOCKER_NS: ${CI_REGISTRY}/digiresilience/link/link-stack/leafcutter
|
||||||
|
|
||||||
metamigo-docker-build:
|
bridge-docker-build:
|
||||||
extends: .docker-build
|
extends: .docker-build
|
||||||
variables:
|
variables:
|
||||||
DOCKER_NS: ${CI_REGISTRY}/digiresilience/link/link-stack/metamigo
|
DOCKER_NS: ${CI_REGISTRY}/digiresilience/link/link-stack/bridge
|
||||||
DOCKERFILE_PATH: ./apps/metamigo-cli/Dockerfile
|
DOCKERFILE_PATH: ./apps/bridge-cli/Dockerfile
|
||||||
|
|
||||||
metamigo-docker-release:
|
bridge-docker-release:
|
||||||
extends: .docker-release
|
extends: .docker-release
|
||||||
variables:
|
variables:
|
||||||
DOCKER_NS: ${CI_REGISTRY}/digiresilience/link/link-stack/metamigo
|
DOCKER_NS: ${CI_REGISTRY}/digiresilience/link/link-stack/bridge
|
||||||
|
|
||||||
elasticsearch-docker-build:
|
elasticsearch-docker-build:
|
||||||
extends: .docker-build
|
extends: .docker-build
|
||||||
|
|
|
||||||
24
README.md
24
README.md
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
Local dev with docker-compose
|
Local dev with docker-compose
|
||||||
|
|
||||||
* Create `link-stack/.env` from Bitwarden `.env for root of link-stack`
|
- Create `link-stack/.env` from Bitwarden `.env for root of link-stack`
|
||||||
* Run local dev with docker-compose:
|
- Run local dev with docker-compose:
|
||||||
```
|
```
|
||||||
git clone ...
|
git clone ...
|
||||||
cd link-stack
|
cd link-stack
|
||||||
|
|
@ -14,23 +14,23 @@ Local dev with docker-compose
|
||||||
|
|
||||||
Or for local dev of a single app
|
Or for local dev of a single app
|
||||||
|
|
||||||
* Create `link-stack/apps/link/.env.local` from Bitwarden `.env.local for link-stack/apps/link`
|
- Create `link-stack/apps/link/.env.local` from Bitwarden `.env.local for link-stack/apps/link`
|
||||||
* Create `link-stack/apps/metamigo-frontend/.metamigo.local.json` from Bitwarden `.metamigo.local.json for link-stack/apps/metamigo/frontend`
|
- Create `link-stack/apps/bridge-frontend/.bridge.local.json` from Bitwarden `.bridge.local.json for link-stack/apps/bridge/frontend`
|
||||||
* Build locally for development:
|
- Build locally for development:
|
||||||
```
|
```
|
||||||
npm install
|
npm install
|
||||||
make dev-metamigo # this starts the containers
|
make dev-bridge # this starts the containers
|
||||||
npm run migrate # this migrates the db
|
npm run migrate # this migrates the db
|
||||||
npm run dev:metamigo # this runs metamigo frontend and api
|
npm run dev:bridge # this runs bridge frontend and api
|
||||||
```
|
```
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
- [ ] Delete old JWT config stuff
|
- [ ] Delete old JWT config stuff
|
||||||
- [ ] Consolidate config
|
- [ ] Consolidate config
|
||||||
- [ ] Complete react-admin upgrade.. make all the metamigo-frontend stuff work
|
- [ ] Complete react-admin upgrade.. make all the bridge-frontend stuff work
|
||||||
* https://marmelab.com/react-admin/Upgrade.html#no-more-prop-injection-in-page-components
|
- https://marmelab.com/react-admin/Upgrade.html#no-more-prop-injection-in-page-components
|
||||||
- [ ] Get metamigo-worker working
|
- [ ] Get bridge-worker working
|
||||||
- [ ] Migrate off mui/styles
|
- [ ] Migrate off mui/styles
|
||||||
* https://mui.com/material-ui/migration/v5-style-changes/
|
- https://mui.com/material-ui/migration/v5-style-changes/
|
||||||
* the codemods might help us?
|
- the codemods might help us?
|
||||||
|
|
|
||||||
|
|
@ -241,7 +241,7 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
|
||||||
fontFamily: poppins.style.fontFamily,
|
fontFamily: poppins.style.fontFamily,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Metamigo
|
CDR Bridge
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
|
@ -2,10 +2,12 @@ import type { Metadata } from "next";
|
||||||
import { InternalLayout } from "./_components/InternalLayout";
|
import { InternalLayout } from "./_components/InternalLayout";
|
||||||
import { LicenseInfo } from "@mui/x-license";
|
import { LicenseInfo } from "@mui/x-license";
|
||||||
|
|
||||||
LicenseInfo.setLicenseKey("7c9bf25d9e240f76e77cbf7d2ba58a23Tz02NjU4OCxFPTE3MTU4NjIzMzQ2ODgsUz1wcm8sTE09c3Vic2NyaXB0aW9uLEtWPTI=");
|
LicenseInfo.setLicenseKey(
|
||||||
|
"7c9bf25d9e240f76e77cbf7d2ba58a23Tz02NjU4OCxFPTE3MTU4NjIzMzQ2ODgsUz1wcm8sTE09c3Vic2NyaXB0aW9uLEtWPTI=",
|
||||||
|
);
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Metamigo",
|
title: "CDR Bridge",
|
||||||
description: "",
|
description: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "metamigo-frontend",
|
"name": "bridge-frontend",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@auth/kysely-adapter": "^0.7.0",
|
"@auth/kysely-adapter": "^1.0.0",
|
||||||
"@emotion/cache": "^11.11.0",
|
"@emotion/cache": "^11.11.0",
|
||||||
"@emotion/react": "^11.11.4",
|
"@emotion/react": "^11.11.4",
|
||||||
"@emotion/styled": "^11.11.5",
|
"@emotion/styled": "^11.11.5",
|
||||||
|
|
@ -17,14 +17,14 @@
|
||||||
"@mui/lab": "^5.0.0-alpha.170",
|
"@mui/lab": "^5.0.0-alpha.170",
|
||||||
"@mui/material": "^5",
|
"@mui/material": "^5",
|
||||||
"@mui/material-nextjs": "^5.15.11",
|
"@mui/material-nextjs": "^5.15.11",
|
||||||
"@mui/x-data-grid-pro": "^7.1.1",
|
"@mui/x-data-grid-pro": "^7.3.0",
|
||||||
"@mui/x-date-pickers-pro": "^7.1.1",
|
"@mui/x-date-pickers-pro": "^7.2.0",
|
||||||
"@mui/x-license": "^7.1.1",
|
"@mui/x-license": "^7.2.0",
|
||||||
"date-fns": "^3.6.0",
|
"date-fns": "^3.6.0",
|
||||||
"kysely": "^0.26.1",
|
"kysely": "^0.26.1",
|
||||||
"material-ui-popup-state": "^5.1.0",
|
"material-ui-popup-state": "^5.1.0",
|
||||||
"mui-chips-input": "^2.1.4",
|
"mui-chips-input": "^2.1.4",
|
||||||
"next": "14.1.4",
|
"next": "14.2.2",
|
||||||
"next-auth": "^4.24.7",
|
"next-auth": "^4.24.7",
|
||||||
"pg": "^8.11.5",
|
"pg": "^8.11.5",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
|
|
@ -41,8 +41,8 @@
|
||||||
"@types/pg": "^8.11.5",
|
"@types/pg": "^8.11.5",
|
||||||
"@types/react": "^18",
|
"@types/react": "^18",
|
||||||
"@types/react-dom": "^18",
|
"@types/react-dom": "^18",
|
||||||
"eslint": "^9",
|
"eslint": "^8",
|
||||||
"eslint-config-next": "14.1.4",
|
"eslint-config-next": "14.2.2",
|
||||||
"ts-config": "*",
|
"ts-config": "*",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
3
apps/bridge-worker/babel.config.json
Normal file
3
apps/bridge-worker/babel.config.json
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"presets": ["@digiresilience/babel-preset-bridge"]
|
||||||
|
}
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
import { SavedVoiceProvider } from "@digiresilience/metamigo-db";
|
import { SavedVoiceProvider } from "@digiresilience/bridge-db";
|
||||||
import Twilio from "twilio";
|
import Twilio from "twilio";
|
||||||
import { CallInstance } from "twilio/lib/rest/api/v2010/account/call";
|
import { CallInstance } from "twilio/lib/rest/api/v2010/account/call";
|
||||||
import { Zammad, getOrCreateUser } from "./zammad";
|
import { Zammad, getOrCreateUser } from "./zammad";
|
||||||
|
|
||||||
export const twilioClientFor = (
|
export const twilioClientFor = (
|
||||||
provider: SavedVoiceProvider
|
provider: SavedVoiceProvider,
|
||||||
): Twilio.Twilio => {
|
): Twilio.Twilio => {
|
||||||
const { accountSid, apiKeySid, apiKeySecret } = provider.credentials;
|
const { accountSid, apiKeySid, apiKeySecret } = provider.credentials;
|
||||||
if (!accountSid || !apiKeySid || !apiKeySecret)
|
if (!accountSid || !apiKeySid || !apiKeySecret)
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`twilio provider ${provider.name} does not have credentials`
|
`twilio provider ${provider.name} does not have credentials`,
|
||||||
);
|
);
|
||||||
|
|
||||||
return Twilio(apiKeySid, apiKeySecret, {
|
return Twilio(apiKeySid, apiKeySecret, {
|
||||||
|
|
@ -20,7 +20,7 @@ export const twilioClientFor = (
|
||||||
|
|
||||||
export const createZammadTicket = async (
|
export const createZammadTicket = async (
|
||||||
call: CallInstance,
|
call: CallInstance,
|
||||||
mp3: Buffer
|
mp3: Buffer,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const title = `Call from ${call.fromFormatted} at ${call.startTime}`;
|
const title = `Call from ${call.fromFormatted} at ${call.startTime}`;
|
||||||
const body = `<ul>
|
const body = `<ul>
|
||||||
|
|
@ -36,7 +36,7 @@ export const createZammadTicket = async (
|
||||||
{
|
{
|
||||||
token: "EviH_WL0p6YUlCoIER7noAZEAPsYA_fVU4FZCKdpq525Vmzzvl8d7dNuP_8d-Amb",
|
token: "EviH_WL0p6YUlCoIER7noAZEAPsYA_fVU4FZCKdpq525Vmzzvl8d7dNuP_8d-Amb",
|
||||||
},
|
},
|
||||||
"https://demo.digiresilience.org"
|
"https://demo.digiresilience.org",
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
const customer = await getOrCreateUser(zammad, call.fromFormatted);
|
const customer = await getOrCreateUser(zammad, call.fromFormatted);
|
||||||
|
|
@ -1,12 +1,16 @@
|
||||||
import pgPromise from "pg-promise";
|
import pgPromise from "pg-promise";
|
||||||
import * as pgMonitor from "pg-monitor";
|
import * as pgMonitor from "pg-monitor";
|
||||||
import { dbInitOptions, IRepositories, AppDatabase } from "@digiresilience/metamigo-db";
|
import {
|
||||||
import config from "@digiresilience/metamigo-config";
|
dbInitOptions,
|
||||||
|
IRepositories,
|
||||||
|
AppDatabase,
|
||||||
|
} from "@digiresilience/bridge-db";
|
||||||
|
import config from "@digiresilience/bridge-config";
|
||||||
import type { IInitOptions } from "pg-promise";
|
import type { IInitOptions } from "pg-promise";
|
||||||
|
|
||||||
export const initDiagnostics = (
|
export const initDiagnostics = (
|
||||||
logSql: boolean,
|
logSql: boolean,
|
||||||
initOpts: IInitOptions<IRepositories>
|
initOpts: IInitOptions<IRepositories>,
|
||||||
): void => {
|
): void => {
|
||||||
if (logSql) {
|
if (logSql) {
|
||||||
pgMonitor.attach(initOpts);
|
pgMonitor.attach(initOpts);
|
||||||
|
|
@ -44,4 +48,4 @@ export const withDb = <T>(f: (db: AppDatabase) => Promise<T>): Promise<T> => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export type { AppDatabase } from "@digiresilience/metamigo-db";
|
export type { AppDatabase } from "@digiresilience/bridge-db";
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { defState } from "@digiresilience/montar";
|
import { defState } from "@digiresilience/montar";
|
||||||
import { configureLogger } from "@digiresilience/metamigo-common";
|
import { configureLogger } from "@digiresilience/bridge-common";
|
||||||
import config from "@digiresilience/metamigo-config";
|
import config from "@digiresilience/bridge-config";
|
||||||
|
|
||||||
export const logger = defState("workerLogger", {
|
export const logger = defState("workerLogger", {
|
||||||
start: async () => configureLogger(config),
|
start: async () => configureLogger(config),
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "metamigo-worker",
|
"name": "bridge-worker",
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"main": "build/main/index.js",
|
"main": "build/main/index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
@ -10,8 +10,8 @@
|
||||||
"html-to-text": "^9.0.5",
|
"html-to-text": "^9.0.5",
|
||||||
"node-fetch": "^3",
|
"node-fetch": "^3",
|
||||||
"pg-promise": "^11.6.0",
|
"pg-promise": "^11.6.0",
|
||||||
"remeda": "^1.57.2",
|
"remeda": "^1.60.1",
|
||||||
"twilio": "^5.0.3"
|
"twilio": "^5.0.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"ts-config": "*",
|
"ts-config": "*",
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
"typedoc": "^0.25.13",
|
"typedoc": "^0.25.13",
|
||||||
"typescript": "^5.4.4"
|
"typescript": "^5.4.5"
|
||||||
},
|
},
|
||||||
"nodemonConfig": {
|
"nodemonConfig": {
|
||||||
"ignore": [
|
"ignore": [
|
||||||
|
|
@ -3,29 +3,35 @@ import { convert } from "html-to-text";
|
||||||
import fetch from "node-fetch";
|
import fetch from "node-fetch";
|
||||||
import { URLSearchParams } from "url";
|
import { URLSearchParams } from "url";
|
||||||
import { withDb, AppDatabase } from "../db";
|
import { withDb, AppDatabase } from "../db";
|
||||||
import { loadConfig } from "@digiresilience/metamigo-config";
|
import { loadConfig } from "@digiresilience/bridge-config";
|
||||||
import { tagMap } from "../lib/tag-map";
|
import { tagMap } from "../lib/tag-map";
|
||||||
|
|
||||||
type FormattedZammadTicket = {
|
type FormattedZammadTicket = {
|
||||||
data: Record<string, unknown>,
|
data: Record<string, unknown>;
|
||||||
predictions: Record<string, unknown>[];
|
predictions: Record<string, unknown>[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const getZammadTickets = async (page: number, minUpdatedTimestamp: Date): Promise<[boolean, FormattedZammadTicket[]]> => {
|
const getZammadTickets = async (
|
||||||
const { leafcutter: { zammadApiUrl, zammadApiKey, contributorName, contributorId } } = await loadConfig();
|
page: number,
|
||||||
|
minUpdatedTimestamp: Date,
|
||||||
|
): Promise<[boolean, FormattedZammadTicket[]]> => {
|
||||||
|
const {
|
||||||
|
leafcutter: { zammadApiUrl, zammadApiKey, contributorName, contributorId },
|
||||||
|
} = await loadConfig();
|
||||||
const headers = { Authorization: `Token ${zammadApiKey}` };
|
const headers = { Authorization: `Token ${zammadApiKey}` };
|
||||||
let shouldContinue = false;
|
let shouldContinue = false;
|
||||||
const docs = [];
|
const docs = [];
|
||||||
const ticketsQuery = new URLSearchParams({
|
const ticketsQuery = new URLSearchParams({
|
||||||
"expand": "true",
|
expand: "true",
|
||||||
"sort_by": "updated_at",
|
sort_by: "updated_at",
|
||||||
"order_by": "asc",
|
order_by: "asc",
|
||||||
"query": "state.name: closed",
|
query: "state.name: closed",
|
||||||
"per_page": "25",
|
per_page: "25",
|
||||||
"page": `${page}`,
|
page: `${page}`,
|
||||||
});
|
});
|
||||||
const rawTickets = await fetch(`${zammadApiUrl}/tickets/search?${ticketsQuery}`,
|
const rawTickets = await fetch(
|
||||||
{ headers }
|
`${zammadApiUrl}/tickets/search?${ticketsQuery}`,
|
||||||
|
{ headers },
|
||||||
);
|
);
|
||||||
const tickets: any = await rawTickets.json();
|
const tickets: any = await rawTickets.json();
|
||||||
console.log({ tickets });
|
console.log({ tickets });
|
||||||
|
|
@ -41,14 +47,25 @@ const getZammadTickets = async (page: number, minUpdatedTimestamp: Date): Promis
|
||||||
shouldContinue = true;
|
shouldContinue = true;
|
||||||
|
|
||||||
if (source_closed_at <= minUpdatedTimestamp) {
|
if (source_closed_at <= minUpdatedTimestamp) {
|
||||||
console.log(`Skipping ticket`, { source_id, source_updated_at, source_closed_at, minUpdatedTimestamp });
|
console.log(`Skipping ticket`, {
|
||||||
|
source_id,
|
||||||
|
source_updated_at,
|
||||||
|
source_closed_at,
|
||||||
|
minUpdatedTimestamp,
|
||||||
|
});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Processing ticket`, { source_id, source_updated_at, source_closed_at, minUpdatedTimestamp });
|
console.log(`Processing ticket`, {
|
||||||
|
source_id,
|
||||||
|
source_updated_at,
|
||||||
|
source_closed_at,
|
||||||
|
minUpdatedTimestamp,
|
||||||
|
});
|
||||||
|
|
||||||
const rawArticles = await fetch(`${zammadApiUrl}/ticket_articles/by_ticket/${source_id}`,
|
const rawArticles = await fetch(
|
||||||
{ headers }
|
`${zammadApiUrl}/ticket_articles/by_ticket/${source_id}`,
|
||||||
|
{ headers },
|
||||||
);
|
);
|
||||||
const articles: any = await rawArticles.json();
|
const articles: any = await rawArticles.json();
|
||||||
let articleText = "";
|
let articleText = "";
|
||||||
|
|
@ -69,7 +86,9 @@ const getZammadTickets = async (page: number, minUpdatedTimestamp: Date): Promis
|
||||||
o_id: source_id,
|
o_id: source_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
const rawTags = await fetch(`${zammadApiUrl}/tags?${tagsQuery}`, { headers });
|
const rawTags = await fetch(`${zammadApiUrl}/tags?${tagsQuery}`, {
|
||||||
|
headers,
|
||||||
|
});
|
||||||
const { tags }: any = await rawTags.json();
|
const { tags }: any = await rawTags.json();
|
||||||
const transformedTags = [];
|
const transformedTags = [];
|
||||||
for (const tag of tags) {
|
for (const tag of tags) {
|
||||||
|
|
@ -88,7 +107,7 @@ const getZammadTickets = async (page: number, minUpdatedTimestamp: Date): Promis
|
||||||
source_created_at,
|
source_created_at,
|
||||||
source_updated_at,
|
source_updated_at,
|
||||||
},
|
},
|
||||||
predictions: []
|
predictions: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = transformedTags.map((tag) => {
|
const result = transformedTags.map((tag) => {
|
||||||
|
|
@ -115,12 +134,17 @@ const getZammadTickets = async (page: number, minUpdatedTimestamp: Date): Promis
|
||||||
return [shouldContinue, docs];
|
return [shouldContinue, docs];
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchFromZammad = async (minUpdatedTimestamp: Date): Promise<FormattedZammadTicket[]> => {
|
const fetchFromZammad = async (
|
||||||
|
minUpdatedTimestamp: Date,
|
||||||
|
): Promise<FormattedZammadTicket[]> => {
|
||||||
const pages = [...Array.from({ length: 10000 }).keys()];
|
const pages = [...Array.from({ length: 10000 }).keys()];
|
||||||
const allTickets: FormattedZammadTicket[] = [];
|
const allTickets: FormattedZammadTicket[] = [];
|
||||||
|
|
||||||
for await (const page of pages) {
|
for await (const page of pages) {
|
||||||
const [shouldContinue, tickets] = await getZammadTickets(page + 1, minUpdatedTimestamp);
|
const [shouldContinue, tickets] = await getZammadTickets(
|
||||||
|
page + 1,
|
||||||
|
minUpdatedTimestamp,
|
||||||
|
);
|
||||||
|
|
||||||
if (!shouldContinue) {
|
if (!shouldContinue) {
|
||||||
break;
|
break;
|
||||||
|
|
@ -135,7 +159,9 @@ const fetchFromZammad = async (minUpdatedTimestamp: Date): Promise<FormattedZamm
|
||||||
};
|
};
|
||||||
|
|
||||||
const sendToLabelStudio = async (tickets: FormattedZammadTicket[]) => {
|
const sendToLabelStudio = async (tickets: FormattedZammadTicket[]) => {
|
||||||
const { leafcutter: { labelStudioApiUrl, labelStudioApiKey } } = await loadConfig();
|
const {
|
||||||
|
leafcutter: { labelStudioApiUrl, labelStudioApiKey },
|
||||||
|
} = await loadConfig();
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
Authorization: `Token ${labelStudioApiKey}`,
|
Authorization: `Token ${labelStudioApiKey}`,
|
||||||
|
|
@ -157,10 +183,14 @@ const sendToLabelStudio = async (tickets: FormattedZammadTicket[]) => {
|
||||||
|
|
||||||
const importLabelStudioTask = async (): Promise<void> => {
|
const importLabelStudioTask = async (): Promise<void> => {
|
||||||
withDb(async (db: AppDatabase) => {
|
withDb(async (db: AppDatabase) => {
|
||||||
const { leafcutter: { contributorName } } = await loadConfig();
|
const {
|
||||||
|
leafcutter: { contributorName },
|
||||||
|
} = await loadConfig();
|
||||||
const settingName = `${contributorName}ImportLabelStudioTask`;
|
const settingName = `${contributorName}ImportLabelStudioTask`;
|
||||||
const res: any = await db.settings.findByName(settingName);
|
const res: any = await db.settings.findByName(settingName);
|
||||||
const startTimestamp = res?.value?.minUpdatedTimestamp ? new Date(res.value.minUpdatedTimestamp as string) : new Date("2023-03-01");
|
const startTimestamp = res?.value?.minUpdatedTimestamp
|
||||||
|
? new Date(res.value.minUpdatedTimestamp as string)
|
||||||
|
: new Date("2023-03-01");
|
||||||
const tickets = await fetchFromZammad(startTimestamp);
|
const tickets = await fetchFromZammad(startTimestamp);
|
||||||
|
|
||||||
if (tickets.length > 0) {
|
if (tickets.length > 0) {
|
||||||
|
|
@ -168,7 +198,9 @@ const importLabelStudioTask = async (): Promise<void> => {
|
||||||
const lastTicket = tickets.pop();
|
const lastTicket = tickets.pop();
|
||||||
const newLastTimestamp = lastTicket.data.source_closed_at;
|
const newLastTimestamp = lastTicket.data.source_closed_at;
|
||||||
console.log({ newLastTimestamp });
|
console.log({ newLastTimestamp });
|
||||||
await db.settings.upsert(settingName, { minUpdatedTimestamp: newLastTimestamp });
|
await db.settings.upsert(settingName, {
|
||||||
|
minUpdatedTimestamp: newLastTimestamp,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import fetch from "node-fetch";
|
import fetch from "node-fetch";
|
||||||
import { URLSearchParams } from "url";
|
import { URLSearchParams } from "url";
|
||||||
import { withDb, AppDatabase } from "../db";
|
import { withDb, AppDatabase } from "../db";
|
||||||
import { loadConfig } from "@digiresilience/metamigo-config";
|
import { loadConfig } from "@digiresilience/bridge-config";
|
||||||
|
|
||||||
type LabelStudioTicket = {
|
type LabelStudioTicket = {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -27,12 +27,11 @@ type LeafcutterTicket = {
|
||||||
source_updated_at: string;
|
source_updated_at: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getLabelStudioTickets = async (page: number): Promise<LabelStudioTicket[]> => {
|
const getLabelStudioTickets = async (
|
||||||
|
page: number,
|
||||||
|
): Promise<LabelStudioTicket[]> => {
|
||||||
const {
|
const {
|
||||||
leafcutter: {
|
leafcutter: { labelStudioApiUrl, labelStudioApiKey },
|
||||||
labelStudioApiUrl,
|
|
||||||
labelStudioApiKey,
|
|
||||||
}
|
|
||||||
} = await loadConfig();
|
} = await loadConfig();
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
|
|
@ -44,8 +43,10 @@ const getLabelStudioTickets = async (page: number): Promise<LabelStudioTicket[]>
|
||||||
page: `${page}`,
|
page: `${page}`,
|
||||||
});
|
});
|
||||||
console.log({ url: `${labelStudioApiUrl}/projects/1/tasks?${ticketsQuery}` });
|
console.log({ url: `${labelStudioApiUrl}/projects/1/tasks?${ticketsQuery}` });
|
||||||
const res = await fetch(`${labelStudioApiUrl}/projects/1/tasks?${ticketsQuery}`,
|
const res = await fetch(
|
||||||
{ headers });
|
`${labelStudioApiUrl}/projects/1/tasks?${ticketsQuery}`,
|
||||||
|
{ headers },
|
||||||
|
);
|
||||||
console.log({ res });
|
console.log({ res });
|
||||||
const tasksResult: any = await res.json();
|
const tasksResult: any = await res.json();
|
||||||
console.log({ tasksResult });
|
console.log({ tasksResult });
|
||||||
|
|
@ -53,7 +54,9 @@ const getLabelStudioTickets = async (page: number): Promise<LabelStudioTicket[]>
|
||||||
return tasksResult;
|
return tasksResult;
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchFromLabelStudio = async (minUpdatedTimestamp: Date): Promise<LabelStudioTicket[]> => {
|
const fetchFromLabelStudio = async (
|
||||||
|
minUpdatedTimestamp: Date,
|
||||||
|
): Promise<LabelStudioTicket[]> => {
|
||||||
const pages = [...Array.from({ length: 10000 }).keys()];
|
const pages = [...Array.from({ length: 10000 }).keys()];
|
||||||
const allDocs: LabelStudioTicket[] = [];
|
const allDocs: LabelStudioTicket[] = [];
|
||||||
|
|
||||||
|
|
@ -85,8 +88,8 @@ const sendToLeafcutter = async (tickets: LabelStudioTicket[]) => {
|
||||||
contributorId,
|
contributorId,
|
||||||
opensearchApiUrl,
|
opensearchApiUrl,
|
||||||
opensearchUsername,
|
opensearchUsername,
|
||||||
opensearchPassword
|
opensearchPassword,
|
||||||
}
|
},
|
||||||
} = await loadConfig();
|
} = await loadConfig();
|
||||||
|
|
||||||
console.log({ tickets });
|
console.log({ tickets });
|
||||||
|
|
@ -96,11 +99,7 @@ const sendToLeafcutter = async (tickets: LabelStudioTicket[]) => {
|
||||||
const {
|
const {
|
||||||
id,
|
id,
|
||||||
annotations,
|
annotations,
|
||||||
data: {
|
data: { source_id, source_created_at, source_updated_at },
|
||||||
source_id,
|
|
||||||
source_created_at,
|
|
||||||
source_updated_at
|
|
||||||
}
|
|
||||||
} = ticket;
|
} = ticket;
|
||||||
|
|
||||||
const getTags = (tags: Record<string, any>[], name: string) =>
|
const getTags = (tags: Record<string, any>[], name: string) =>
|
||||||
|
|
@ -127,7 +126,7 @@ const sendToLeafcutter = async (tickets: LabelStudioTicket[]) => {
|
||||||
origin: contributorId,
|
origin: contributorId,
|
||||||
origin_id: source_id as string,
|
origin_id: source_id as string,
|
||||||
source_created_at: source_created_at as string,
|
source_created_at: source_created_at as string,
|
||||||
source_updated_at: source_updated_at as string
|
source_updated_at: source_updated_at as string,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -145,19 +144,30 @@ const sendToLeafcutter = async (tickets: LabelStudioTicket[]) => {
|
||||||
console.log({ result });
|
console.log({ result });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const importLeafcutterTask = async (): Promise<void> => {
|
const importLeafcutterTask = async (): Promise<void> => {
|
||||||
withDb(async (db: AppDatabase) => {
|
withDb(async (db: AppDatabase) => {
|
||||||
const { leafcutter: { contributorName } } = await loadConfig();
|
const {
|
||||||
|
leafcutter: { contributorName },
|
||||||
|
} = await loadConfig();
|
||||||
const settingName = `${contributorName}ImportLeafcutterTask`;
|
const settingName = `${contributorName}ImportLeafcutterTask`;
|
||||||
const res: any = await db.settings.findByName(settingName);
|
const res: any = await db.settings.findByName(settingName);
|
||||||
const startTimestamp = res?.value?.minUpdatedTimestamp ? new Date(res.value.minUpdatedTimestamp as string) : new Date("2023-03-01");
|
const startTimestamp = res?.value?.minUpdatedTimestamp
|
||||||
|
? new Date(res.value.minUpdatedTimestamp as string)
|
||||||
|
: new Date("2023-03-01");
|
||||||
const newLastTimestamp = new Date();
|
const newLastTimestamp = new Date();
|
||||||
console.log({ contributorName, settingName, res, startTimestamp, newLastTimestamp });
|
console.log({
|
||||||
|
contributorName,
|
||||||
|
settingName,
|
||||||
|
res,
|
||||||
|
startTimestamp,
|
||||||
|
newLastTimestamp,
|
||||||
|
});
|
||||||
const tickets = await fetchFromLabelStudio(startTimestamp);
|
const tickets = await fetchFromLabelStudio(startTimestamp);
|
||||||
console.log({ tickets });
|
console.log({ tickets });
|
||||||
await sendToLeafcutter(tickets);
|
await sendToLeafcutter(tickets);
|
||||||
await db.settings.upsert(settingName, { minUpdatedTimestamp: newLastTimestamp });
|
await db.settings.upsert(settingName, {
|
||||||
|
minUpdatedTimestamp: newLastTimestamp,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import Twilio from "twilio";
|
import Twilio from "twilio";
|
||||||
import config from "@digiresilience/metamigo-config";
|
import config from "@digiresilience/bridge-config";
|
||||||
import { withDb, AppDatabase } from "../db";
|
import { withDb, AppDatabase } from "../db";
|
||||||
|
|
||||||
interface VoiceLineDeleteTaskOptions {
|
interface VoiceLineDeleteTaskOptions {
|
||||||
|
|
@ -9,7 +9,7 @@ interface VoiceLineDeleteTaskOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
const voiceLineDeleteTask = async (
|
const voiceLineDeleteTask = async (
|
||||||
payload: VoiceLineDeleteTaskOptions
|
payload: VoiceLineDeleteTaskOptions,
|
||||||
): Promise<void> =>
|
): Promise<void> =>
|
||||||
withDb(async (db: AppDatabase) => {
|
withDb(async (db: AppDatabase) => {
|
||||||
const { voiceLineId, providerId, providerLineSid } = payload;
|
const { voiceLineId, providerId, providerLineSid } = payload;
|
||||||
|
|
@ -19,7 +19,7 @@ const voiceLineDeleteTask = async (
|
||||||
const { accountSid, apiKeySid, apiKeySecret } = provider.credentials;
|
const { accountSid, apiKeySid, apiKeySecret } = provider.credentials;
|
||||||
if (!accountSid || !apiKeySid || !apiKeySecret)
|
if (!accountSid || !apiKeySid || !apiKeySecret)
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`twilio provider ${provider.name} does not have credentials`
|
`twilio provider ${provider.name} does not have credentials`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const client = Twilio(apiKeySid, apiKeySecret, {
|
const client = Twilio(apiKeySid, apiKeySecret, {
|
||||||
|
|
@ -30,7 +30,7 @@ const voiceLineDeleteTask = async (
|
||||||
if (
|
if (
|
||||||
number &&
|
number &&
|
||||||
number.voiceUrl ===
|
number.voiceUrl ===
|
||||||
`${config.frontend.url}/api/v1/voice/twilio/record/${voiceLineId}`
|
`${config.frontend.url}/api/v1/voice/twilio/record/${voiceLineId}`
|
||||||
)
|
)
|
||||||
await client.incomingPhoneNumbers(providerLineSid).update({
|
await client.incomingPhoneNumbers(providerLineSid).update({
|
||||||
voiceUrl: "",
|
voiceUrl: "",
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import Twilio from "twilio";
|
import Twilio from "twilio";
|
||||||
import config from "@digiresilience/metamigo-config";
|
import config from "@digiresilience/bridge-config";
|
||||||
import { withDb, AppDatabase } from "../db";
|
import { withDb, AppDatabase } from "../db";
|
||||||
|
|
||||||
interface VoiceLineUpdateTaskOptions {
|
interface VoiceLineUpdateTaskOptions {
|
||||||
|
|
@ -7,7 +7,7 @@ interface VoiceLineUpdateTaskOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
const voiceLineUpdateTask = async (
|
const voiceLineUpdateTask = async (
|
||||||
payload: VoiceLineUpdateTaskOptions
|
payload: VoiceLineUpdateTaskOptions,
|
||||||
): Promise<void> =>
|
): Promise<void> =>
|
||||||
withDb(async (db: AppDatabase) => {
|
withDb(async (db: AppDatabase) => {
|
||||||
const { voiceLineId } = payload;
|
const { voiceLineId } = payload;
|
||||||
|
|
@ -22,7 +22,7 @@ const voiceLineUpdateTask = async (
|
||||||
const { accountSid, apiKeySid, apiKeySecret } = provider.credentials;
|
const { accountSid, apiKeySid, apiKeySecret } = provider.credentials;
|
||||||
if (!accountSid || !apiKeySid || !apiKeySecret)
|
if (!accountSid || !apiKeySid || !apiKeySecret)
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`twilio provider ${provider.name} does not have credentials`
|
`twilio provider ${provider.name} does not have credentials`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const client = Twilio(apiKeySid, apiKeySecret, {
|
const client = Twilio(apiKeySid, apiKeySecret, {
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import * as Worker from "graphile-worker";
|
import * as Worker from "graphile-worker";
|
||||||
import { defState } from "@digiresilience/montar";
|
import { defState } from "@digiresilience/montar";
|
||||||
import config from "@digiresilience/metamigo-config";
|
import config from "@digiresilience/bridge-config";
|
||||||
|
|
||||||
const startWorkerUtils = async (): Promise<Worker.WorkerUtils> => {
|
const startWorkerUtils = async (): Promise<Worker.WorkerUtils> => {
|
||||||
const workerUtils = await Worker.makeWorkerUtils({
|
const workerUtils = await Worker.makeWorkerUtils({
|
||||||
|
|
@ -20,15 +20,15 @@
|
||||||
"@mui/icons-material": "^5",
|
"@mui/icons-material": "^5",
|
||||||
"@mui/lab": "^5.0.0-alpha.170",
|
"@mui/lab": "^5.0.0-alpha.170",
|
||||||
"@mui/material": "^5",
|
"@mui/material": "^5",
|
||||||
"@mui/x-data-grid-pro": "^7.1.1",
|
"@mui/x-data-grid-pro": "^7.3.0",
|
||||||
"@mui/x-date-pickers-pro": "^7.1.1",
|
"@mui/x-date-pickers-pro": "^7.2.0",
|
||||||
"@opensearch-project/opensearch": "^2.6.0",
|
"@opensearch-project/opensearch": "^2.7.0",
|
||||||
"cryptr": "^6.3.0",
|
"cryptr": "^6.3.0",
|
||||||
"date-fns": "^3.6.0",
|
"date-fns": "^3.6.0",
|
||||||
"http-proxy-middleware": "^3.0.0",
|
"http-proxy-middleware": "^3.0.0",
|
||||||
"leafcutter-ui": "*",
|
"leafcutter-ui": "*",
|
||||||
"material-ui-popup-state": "^5.1.0",
|
"material-ui-popup-state": "^5.1.0",
|
||||||
"next": "14.1.4",
|
"next": "14.2.2",
|
||||||
"next-auth": "^4.24.7",
|
"next-auth": "^4.24.7",
|
||||||
"next-http-proxy-middleware": "^1.2.6",
|
"next-http-proxy-middleware": "^1.2.6",
|
||||||
"opensearch-common": "*",
|
"opensearch-common": "*",
|
||||||
|
|
@ -47,17 +47,17 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.24.4",
|
"@babel/core": "^7.24.4",
|
||||||
"@types/node": "^20.12.6",
|
"@types/node": "^20.12.7",
|
||||||
"@types/react": "18.2.75",
|
"@types/react": "18.2.79",
|
||||||
"@types/uuid": "^9.0.8",
|
"@types/uuid": "^9.0.8",
|
||||||
"babel-loader": "^9.1.3",
|
"babel-loader": "^9.1.3",
|
||||||
"eslint": "^9.0.0",
|
"eslint": "^8.0.0",
|
||||||
"eslint-config-next": "^14.1.4",
|
"eslint-config-next": "^14.2.2",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.29.1",
|
||||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
"eslint-plugin-react": "^7.34.1",
|
"eslint-plugin-react": "^7.34.1",
|
||||||
"typescript": "5.4.4"
|
"typescript": "5.4.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,114 +53,115 @@ const MenuItem = ({
|
||||||
}: any) => {
|
}: any) => {
|
||||||
const { roboto } = fonts;
|
const { roboto } = fonts;
|
||||||
|
|
||||||
return (<Link href={href} target={target}>
|
return (
|
||||||
<ListItemButton
|
<Link href={href} target={target}>
|
||||||
sx={{
|
<ListItemButton
|
||||||
p: 0,
|
sx={{
|
||||||
mb: 1,
|
p: 0,
|
||||||
bl: iconSize === 0 ? "1px solid white" : "inherit",
|
mb: 1,
|
||||||
}}
|
bl: iconSize === 0 ? "1px solid white" : "inherit",
|
||||||
selected={selected}
|
}}
|
||||||
>
|
selected={selected}
|
||||||
{iconSize > 0 ? (
|
>
|
||||||
<ListItemIcon
|
{iconSize > 0 ? (
|
||||||
sx={{
|
<ListItemIcon
|
||||||
color: `white`,
|
|
||||||
minWidth: 0,
|
|
||||||
mr: 2,
|
|
||||||
textAlign: "center",
|
|
||||||
margin: open ? "0 8 0 0" : "0 auto",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
sx={{
|
||||||
width: iconSize,
|
color: `white`,
|
||||||
height: iconSize,
|
minWidth: 0,
|
||||||
mr: 0.5,
|
mr: 2,
|
||||||
mt: "-4px",
|
textAlign: "center",
|
||||||
|
margin: open ? "0 8 0 0" : "0 auto",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon />
|
<Box
|
||||||
</Box>
|
|
||||||
</ListItemIcon>
|
|
||||||
) : (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: 30,
|
|
||||||
height: "28px",
|
|
||||||
position: "relative",
|
|
||||||
ml: "9px",
|
|
||||||
mr: "1px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: "1px",
|
|
||||||
height: "56px",
|
|
||||||
backgroundColor: "white",
|
|
||||||
position: "absolute",
|
|
||||||
left: "3px",
|
|
||||||
top: "-10px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: "42px",
|
|
||||||
height: "42px",
|
|
||||||
position: "absolute",
|
|
||||||
top: "-27px",
|
|
||||||
left: "3px",
|
|
||||||
border: "solid 1px #fff",
|
|
||||||
borderColor: "transparent transparent transparent #fff",
|
|
||||||
borderRadius: "60px",
|
|
||||||
rotate: "-35deg",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
{open && (
|
|
||||||
<ListItemText
|
|
||||||
inset={inset}
|
|
||||||
primary={
|
|
||||||
<Typography
|
|
||||||
variant="body1"
|
|
||||||
sx={{
|
sx={{
|
||||||
fontSize: 16,
|
width: iconSize,
|
||||||
fontFamily: roboto.style.fontFamily,
|
height: iconSize,
|
||||||
fontWeight: "bold",
|
mr: 0.5,
|
||||||
border: 0,
|
mt: "-4px",
|
||||||
textAlign: "left",
|
|
||||||
color: "white",
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{name}
|
<Icon />
|
||||||
</Typography>
|
</Box>
|
||||||
}
|
</ListItemIcon>
|
||||||
/>
|
) : (
|
||||||
)}
|
<Box
|
||||||
{badge && badge > 0 ? (
|
|
||||||
<ListItemSecondaryAction>
|
|
||||||
<Typography
|
|
||||||
color="textSecondary"
|
|
||||||
variant="body1"
|
|
||||||
className="badge"
|
|
||||||
sx={{
|
sx={{
|
||||||
backgroundColor: "#FFB620",
|
width: 30,
|
||||||
color: "black !important",
|
height: "28px",
|
||||||
borderRadius: 10,
|
position: "relative",
|
||||||
px: 1,
|
ml: "9px",
|
||||||
fontSize: 12,
|
mr: "1px",
|
||||||
fontWeight: "bold",
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{badge}
|
<Box
|
||||||
</Typography>
|
sx={{
|
||||||
</ListItemSecondaryAction>
|
width: "1px",
|
||||||
) : null}
|
height: "56px",
|
||||||
</ListItemButton>
|
backgroundColor: "white",
|
||||||
</Link>
|
position: "absolute",
|
||||||
);
|
left: "3px",
|
||||||
}
|
top: "-10px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: "42px",
|
||||||
|
height: "42px",
|
||||||
|
position: "absolute",
|
||||||
|
top: "-27px",
|
||||||
|
left: "3px",
|
||||||
|
border: "solid 1px #fff",
|
||||||
|
borderColor: "transparent transparent transparent #fff",
|
||||||
|
borderRadius: "60px",
|
||||||
|
rotate: "-35deg",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
{open && (
|
||||||
|
<ListItemText
|
||||||
|
inset={inset}
|
||||||
|
primary={
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
sx={{
|
||||||
|
fontSize: 16,
|
||||||
|
fontFamily: roboto.style.fontFamily,
|
||||||
|
fontWeight: "bold",
|
||||||
|
border: 0,
|
||||||
|
textAlign: "left",
|
||||||
|
color: "white",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{badge && badge > 0 ? (
|
||||||
|
<ListItemSecondaryAction>
|
||||||
|
<Typography
|
||||||
|
color="textSecondary"
|
||||||
|
variant="body1"
|
||||||
|
className="badge"
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "#FFB620",
|
||||||
|
color: "black !important",
|
||||||
|
borderRadius: 10,
|
||||||
|
px: 1,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: "bold",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{badge}
|
||||||
|
</Typography>
|
||||||
|
</ListItemSecondaryAction>
|
||||||
|
) : null}
|
||||||
|
</ListItemButton>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
interface SidebarProps {
|
interface SidebarProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
|
|
@ -577,13 +578,13 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
|
||||||
selected={pathname.endsWith("/admin/zammad")}
|
selected={pathname.endsWith("/admin/zammad")}
|
||||||
open={open}
|
open={open}
|
||||||
/>
|
/>
|
||||||
{false && roles.includes("metamigo") && (
|
{false && roles.includes("bridge") && (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
name="Metamigo"
|
name="Bridge"
|
||||||
href="/admin/metamigo"
|
href="/admin/bridge"
|
||||||
Icon={FeaturedPlayListIcon}
|
Icon={FeaturedPlayListIcon}
|
||||||
iconSize={0}
|
iconSize={0}
|
||||||
selected={pathname.endsWith("/admin/metamigo")}
|
selected={pathname.endsWith("/admin/bridge")}
|
||||||
open={open}
|
open={open}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@ const nextConfig = {
|
||||||
experimental: {
|
experimental: {
|
||||||
missingSuspenseWithCSRBailout: false,
|
missingSuspenseWithCSRBailout: false,
|
||||||
},
|
},
|
||||||
transpilePackages: ["leafcutter-ui", "metamigo-ui", "opensearch-common", "ui"],
|
transpilePackages: ["leafcutter-ui", "bridge-ui", "opensearch-common", "ui"],
|
||||||
publicRuntimeConfig: {
|
publicRuntimeConfig: {
|
||||||
linkURL: process.env.LINK_URL ?? "http://localhost:3000",
|
linkURL: process.env.LINK_URL ?? "http://localhost:3000",
|
||||||
metamigoURL: process.env.METAMIGO_URL ?? "http://localhost:8002",
|
bridgeURL: process.env.BRIDGE_URL ?? "http://localhost:8002",
|
||||||
labelStudioURL: process.env.LABEL_STUDIO_URL ?? "http://localhost:8006",
|
labelStudioURL: process.env.LABEL_STUDIO_URL ?? "http://localhost:8006",
|
||||||
muiLicenseKey: process.env.MUI_LICENSE_KEY ?? "",
|
muiLicenseKey: process.env.MUI_LICENSE_KEY ?? "",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,15 @@
|
||||||
"@mui/icons-material": "^5",
|
"@mui/icons-material": "^5",
|
||||||
"@mui/lab": "^5.0.0-alpha.170",
|
"@mui/lab": "^5.0.0-alpha.170",
|
||||||
"@mui/material": "^5",
|
"@mui/material": "^5",
|
||||||
"@mui/x-data-grid-pro": "^7.1.1",
|
"@mui/x-data-grid-pro": "^7.3.0",
|
||||||
"@mui/x-date-pickers-pro": "^7.1.1",
|
"@mui/x-date-pickers-pro": "^7.2.0",
|
||||||
"date-fns": "^3.6.0",
|
"date-fns": "^3.6.0",
|
||||||
"graphql-request": "^6.1.0",
|
"graphql-request": "^6.1.0",
|
||||||
"leafcutter-ui": "*",
|
"leafcutter-ui": "*",
|
||||||
"material-ui-popup-state": "^5.1.0",
|
"material-ui-popup-state": "^5.1.0",
|
||||||
"metamigo-ui": "*",
|
"bridge-ui": "*",
|
||||||
"mui-chips-input": "^2.1.4",
|
"mui-chips-input": "^2.1.4",
|
||||||
"next": "14.1.4",
|
"next": "14.2.2",
|
||||||
"next-auth": "^4.24.7",
|
"next-auth": "^4.24.7",
|
||||||
"opensearch-common": "*",
|
"opensearch-common": "*",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
|
|
@ -42,17 +42,17 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.24.4",
|
"@babel/core": "^7.24.4",
|
||||||
"@types/node": "^20.12.6",
|
"@types/node": "^20.12.7",
|
||||||
"@types/react": "18.2.75",
|
"@types/react": "18.2.79",
|
||||||
"@types/uuid": "^9.0.8",
|
"@types/uuid": "^9.0.8",
|
||||||
"babel-loader": "^9.1.3",
|
"babel-loader": "^9.1.3",
|
||||||
"eslint": "^9.0.0",
|
"eslint": "^8.0.0",
|
||||||
"eslint-config-next": "^14.1.4",
|
"eslint-config-next": "^14.2.2",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.29.1",
|
||||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
"eslint-plugin-react": "^7.34.1",
|
"eslint-plugin-react": "^7.34.1",
|
||||||
"typescript": "5.4.4"
|
"typescript": "5.4.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
@digiresilience:registry=https://gitlab.com/api/v4/packages/npm/
|
|
||||||
@guardianproject-ops:registry=https://gitlab.com/api/v4/packages/npm/
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"presets": [
|
|
||||||
"@digiresilience/babel-preset-metamigo"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
echo "Creating the Metamigo database and the roles"
|
echo "Creating the Bridge database and the roles"
|
||||||
# We're using 'template1' because we know it should exist. We should not actually change this database.
|
# We're using 'template1' because we know it should exist. We should not actually change this database.
|
||||||
psql -Xv ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname template1 <<EOF
|
psql -Xv ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname template1 <<EOF
|
||||||
CREATE ROLE ${DATABASE_OWNER} WITH LOGIN PASSWORD '${DATABASE_PASSWORD}';
|
CREATE ROLE ${DATABASE_OWNER} WITH LOGIN PASSWORD '${DATABASE_PASSWORD}';
|
||||||
|
|
@ -32,4 +32,3 @@ CREATE ROLE app_admin WITH IN ROLE app_user;
|
||||||
GRANT app_anonymous TO ${DATABASE_AUTHENTICATOR};
|
GRANT app_anonymous TO ${DATABASE_AUTHENTICATOR};
|
||||||
GRANT app_admin TO ${DATABASE_AUTHENTICATOR};
|
GRANT app_admin TO ${DATABASE_AUTHENTICATOR};
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
echo "Creating Metamigo admin user"
|
echo "Creating Bridge admin user"
|
||||||
psql -Xv ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$DATABASE_NAME" <<EOF
|
psql -Xv ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$DATABASE_NAME" <<EOF
|
||||||
INSERT INTO app_public.users(email, name, user_role, is_active, created_by)
|
INSERT INTO app_public.users(email, name, user_role, is_active, created_by)
|
||||||
VALUES('$GITLAB_EMAIL_ADDRESS', 'Admin', 'admin'::app_public.role_type, true, '')
|
VALUES('$GITLAB_EMAIL_ADDRESS', 'Admin', 'admin'::app_public.role_type, true, '')
|
||||||
|
|
|
||||||
49
docker/compose/bridge.yml
Normal file
49
docker/compose/bridge.yml
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
version: "3.4"
|
||||||
|
|
||||||
|
x-global-vars: &common-global-variables
|
||||||
|
TZ: Etc/UTC
|
||||||
|
|
||||||
|
x-bridge-vars: &common-bridge-variables
|
||||||
|
DATABASE_HOST: "bridge-postgresql"
|
||||||
|
DATABASE_NAME: "bridge"
|
||||||
|
DATABASE_ROOT_OWNER: "root"
|
||||||
|
DATABASE_ROOT_PASSWORD: ${BRIDGE_DATABASE_ROOT_PASSWORD}
|
||||||
|
DATABASE_OWNER: "bridge"
|
||||||
|
DATABASE_PASSWORD: ${BRIDGE_DATABASE_PASSWORD}
|
||||||
|
DATABASE_VISITOR: "app_visitor"
|
||||||
|
DATABASE_AUTHENTICATOR: "app_graphile_auth"
|
||||||
|
DATABASE_AUTHENTICATOR_PASSWORD: ${BRIDGE_DATABASE_AUTHENTICATOR_PASSWORD}
|
||||||
|
DATABASE_URL: "postgresql://bridge:${BRIDGE_DATABASE_PASSWORD}@bridge-postgresql/bridge"
|
||||||
|
WORKER_DATABASE_URL: "postgresql://bridge:${BRIDGE_DATABASE_PASSWORD}@bridge-postgresql/bridge"
|
||||||
|
SHADOW_DATABASE_URL: "postgresql://bridge:${BRIDGE_DATABASE_PASSWORD}@bridge-postgresql/bridge_shadow"
|
||||||
|
ROOT_DATABASE_URL: "postgresql://bridge:${BRIDGE_DATABASE_PASSWORD}@bridge-postgresql/template1"
|
||||||
|
APP_ROOT_DATABASE_URL: "postgresql://root:${BRIDGE_DATABASE_ROOT_PASSWORD}@bridge-postgresql/bridge"
|
||||||
|
DATABASE_AUTH_URL: "postgresql://app_graphile_auth:${BRIDGE_DATABASE_AUTHENTICATOR_PASSWORD}@bridge-postgresql/bridge"
|
||||||
|
CORS_ALLOWED_ORIGINS: "https://bridge-api,${BRIDGE_DOMAIN},http://localhost:3000,http://127.0.0.1:3000"
|
||||||
|
FRONTEND_URL: ${BRIDGE_DOMAIN}
|
||||||
|
API_URL: "http://bridge-api:3001"
|
||||||
|
NEXTAUTH_URL: ${BRIDGE_DOMAIN}
|
||||||
|
NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
|
||||||
|
NEXTAUTH_AUDIENCE: ${NEXTAUTH_AUDIENCE}
|
||||||
|
NEXTAUTH_SIGNING_KEY_B64: ${NEXTAUTH_SIGNING_KEY_B64}
|
||||||
|
NEXTAUTH_ENCRYPTION_KEY_B64: ${NEXTAUTH_ENCRYPTION_KEY_B64}
|
||||||
|
GITLAB_EMAIL_ADDRESS: ${GITLAB_EMAIL_ADDRESS}
|
||||||
|
GITLAB_ID: ${GITLAB_ID}
|
||||||
|
GITLAB_SECRET: ${GITLAB_SECRET}
|
||||||
|
SIGNALD_ENABLED: "true"
|
||||||
|
SIGNALD_SOCKET: /signald/signald.sock
|
||||||
|
|
||||||
|
services:
|
||||||
|
bridge-frontend:
|
||||||
|
build: ../../apps/bridge-frontend
|
||||||
|
container_name: bridge-frontend
|
||||||
|
restart: ${RESTART}
|
||||||
|
ports:
|
||||||
|
- 8006:3000
|
||||||
|
environment: *common-bridge-variables
|
||||||
|
|
||||||
|
bridge-worker:
|
||||||
|
build: ../../apps/bridge-worker
|
||||||
|
container_name: bridge-worker
|
||||||
|
restart: ${RESTART}
|
||||||
|
environment: *common-bridge-variables
|
||||||
|
|
@ -17,7 +17,7 @@ services:
|
||||||
ZAMMAD_VIRUAL_HOST: ${ZAMMAD_VIRTUAL_HOST}
|
ZAMMAD_VIRUAL_HOST: ${ZAMMAD_VIRTUAL_HOST}
|
||||||
LINK_URL: http://localhost:3000
|
LINK_URL: http://localhost:3000
|
||||||
LEAFCUTTER_URL: https://lc.digiresilience.org
|
LEAFCUTTER_URL: https://lc.digiresilience.org
|
||||||
METAMIGO_URL: http://metamigo-frontend:3000
|
BRIDGE_URL: http://bridge-frontend:3000
|
||||||
ZAMMAD_URL: http://zammad-nginx:8080
|
ZAMMAD_URL: http://zammad-nginx:8080
|
||||||
NEXTAUTH_URL: ${LINK_URL}
|
NEXTAUTH_URL: ${LINK_URL}
|
||||||
NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
|
NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
|
||||||
|
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
version: "3.4"
|
|
||||||
|
|
||||||
x-global-vars: &common-global-variables
|
|
||||||
TZ: Etc/UTC
|
|
||||||
|
|
||||||
x-metamigo-vars: &common-metamigo-variables
|
|
||||||
DATABASE_HOST: "metamigo-postgresql"
|
|
||||||
DATABASE_NAME: "metamigo"
|
|
||||||
DATABASE_ROOT_OWNER: "root"
|
|
||||||
DATABASE_ROOT_PASSWORD: ${METAMIGO_DATABASE_ROOT_PASSWORD}
|
|
||||||
DATABASE_OWNER: "metamigo"
|
|
||||||
DATABASE_PASSWORD: ${METAMIGO_DATABASE_PASSWORD}
|
|
||||||
DATABASE_VISITOR: "app_visitor"
|
|
||||||
DATABASE_AUTHENTICATOR: "app_graphile_auth"
|
|
||||||
DATABASE_AUTHENTICATOR_PASSWORD: ${METAMIGO_DATABASE_AUTHENTICATOR_PASSWORD}
|
|
||||||
DATABASE_URL: "postgresql://metamigo:${METAMIGO_DATABASE_PASSWORD}@metamigo-postgresql/metamigo"
|
|
||||||
WORKER_DATABASE_URL: "postgresql://metamigo:${METAMIGO_DATABASE_PASSWORD}@metamigo-postgresql/metamigo"
|
|
||||||
SHADOW_DATABASE_URL: "postgresql://metamigo:${METAMIGO_DATABASE_PASSWORD}@metamigo-postgresql/metamigo_shadow"
|
|
||||||
ROOT_DATABASE_URL: "postgresql://metamigo:${METAMIGO_DATABASE_PASSWORD}@metamigo-postgresql/template1"
|
|
||||||
APP_ROOT_DATABASE_URL: "postgresql://root:${METAMIGO_DATABASE_ROOT_PASSWORD}@metamigo-postgresql/metamigo"
|
|
||||||
DATABASE_AUTH_URL: "postgresql://app_graphile_auth:${METAMIGO_DATABASE_AUTHENTICATOR_PASSWORD}@metamigo-postgresql/metamigo"
|
|
||||||
CORS_ALLOWED_ORIGINS: "https://metamigo-api,${METAMIGO_DOMAIN},http://localhost:3000,http://127.0.0.1:3000"
|
|
||||||
FRONTEND_URL: ${METAMIGO_DOMAIN}
|
|
||||||
API_URL: "http://metamigo-api:3001"
|
|
||||||
NEXTAUTH_URL: ${METAMIGO_DOMAIN}
|
|
||||||
NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
|
|
||||||
NEXTAUTH_AUDIENCE: ${NEXTAUTH_AUDIENCE}
|
|
||||||
NEXTAUTH_SIGNING_KEY_B64: ${NEXTAUTH_SIGNING_KEY_B64}
|
|
||||||
NEXTAUTH_ENCRYPTION_KEY_B64: ${NEXTAUTH_ENCRYPTION_KEY_B64}
|
|
||||||
GITLAB_EMAIL_ADDRESS: ${GITLAB_EMAIL_ADDRESS}
|
|
||||||
GITLAB_ID: ${GITLAB_ID}
|
|
||||||
GITLAB_SECRET: ${GITLAB_SECRET}
|
|
||||||
SIGNALD_ENABLED: "true"
|
|
||||||
SIGNALD_SOCKET: /signald/signald.sock
|
|
||||||
|
|
||||||
services:
|
|
||||||
metamigo-frontend:
|
|
||||||
build: ../../apps/metamigo-frontend
|
|
||||||
container_name: metamigo-frontend
|
|
||||||
restart: ${RESTART}
|
|
||||||
ports:
|
|
||||||
- 8006:3000
|
|
||||||
environment: *common-metamigo-variables
|
|
||||||
|
|
||||||
metamigo-worker:
|
|
||||||
build: ../../apps/metamigo-worker
|
|
||||||
container_name: metamigo-worker
|
|
||||||
restart: ${RESTART}
|
|
||||||
environment: *common-metamigo-variables
|
|
||||||
|
|
@ -17,26 +17,26 @@ x-zammad-vars: &common-zammad-variables
|
||||||
ELASTICSEARCH_SSL_VERIFY: false # this doesn't set es_ssl_verify as expected, but ideally it would
|
ELASTICSEARCH_SSL_VERIFY: false # this doesn't set es_ssl_verify as expected, but ideally it would
|
||||||
ELASTICSEARCH_SCHEMA: "https"
|
ELASTICSEARCH_SCHEMA: "https"
|
||||||
|
|
||||||
x-metamigo-vars: &common-metamigo-variables
|
x-bridge-vars: &common-bridge-variables
|
||||||
DATABASE_HOST: "postgresql"
|
DATABASE_HOST: "postgresql"
|
||||||
DATABASE_NAME: "metamigo"
|
DATABASE_NAME: "bridge"
|
||||||
DATABASE_ROOT_OWNER: "root"
|
DATABASE_ROOT_OWNER: "root"
|
||||||
DATABASE_ROOT_PASSWORD: ${METAMIGO_DATABASE_ROOT_PASSWORD}
|
DATABASE_ROOT_PASSWORD: ${BRIDGE_DATABASE_ROOT_PASSWORD}
|
||||||
DATABASE_OWNER: "metamigo"
|
DATABASE_OWNER: "bridge"
|
||||||
DATABASE_PASSWORD: ${METAMIGO_DATABASE_PASSWORD}
|
DATABASE_PASSWORD: ${BRIDGE_DATABASE_PASSWORD}
|
||||||
DATABASE_VISITOR: "app_visitor"
|
DATABASE_VISITOR: "app_visitor"
|
||||||
DATABASE_AUTHENTICATOR: "app_graphile_auth"
|
DATABASE_AUTHENTICATOR: "app_graphile_auth"
|
||||||
DATABASE_AUTHENTICATOR_PASSWORD: ${METAMIGO_DATABASE_AUTHENTICATOR_PASSWORD}
|
DATABASE_AUTHENTICATOR_PASSWORD: ${BRIDGE_DATABASE_AUTHENTICATOR_PASSWORD}
|
||||||
DATABASE_URL: "postgresql://metamigo:${METAMIGO_DATABASE_PASSWORD}@metamigo-postgresql/metamigo"
|
DATABASE_URL: "postgresql://bridge:${BRIDGE_DATABASE_PASSWORD}@bridge-postgresql/bridge"
|
||||||
WORKER_DATABASE_URL: "postgresql://metamigo:${METAMIGO_DATABASE_PASSWORD}@metamigo-postgresql/metamigo"
|
WORKER_DATABASE_URL: "postgresql://bridge:${BRIDGE_DATABASE_PASSWORD}@bridge-postgresql/bridge"
|
||||||
SHADOW_DATABASE_URL: "postgresql://metamigo:${METAMIGO_DATABASE_PASSWORD}@metamigo-postgresql/metamigo_shadow"
|
SHADOW_DATABASE_URL: "postgresql://bridge:${BRIDGE_DATABASE_PASSWORD}@bridge-postgresql/bridge_shadow"
|
||||||
ROOT_DATABASE_URL: "postgresql://metamigo:${METAMIGO_DATABASE_PASSWORD}@metamigo-postgresql/template1"
|
ROOT_DATABASE_URL: "postgresql://bridge:${BRIDGE_DATABASE_PASSWORD}@bridge-postgresql/template1"
|
||||||
APP_ROOT_DATABASE_URL: "postgresql://root:${METAMIGO_DATABASE_ROOT_PASSWORD}@metamigo-postgresql/metamigo"
|
APP_ROOT_DATABASE_URL: "postgresql://root:${BRIDGE_DATABASE_ROOT_PASSWORD}@bridge-postgresql/bridge"
|
||||||
DATABASE_AUTH_URL: "postgresql://app_graphile_auth:${METAMIGO_DATABASE_AUTHENTICATOR_PASSWORD}@metamigo-postgresql/metamigo"
|
DATABASE_AUTH_URL: "postgresql://app_graphile_auth:${BRIDGE_DATABASE_AUTHENTICATOR_PASSWORD}@bridge-postgresql/bridge"
|
||||||
CORS_ALLOWED_ORIGINS: "https://metamigo-api,${METAMIGO_DOMAIN},http://localhost:3000,http://127.0.0.1:3000"
|
CORS_ALLOWED_ORIGINS: "https://bridge-api,${BRIDGE_DOMAIN},http://localhost:3000,http://127.0.0.1:3000"
|
||||||
FRONTEND_URL: ${METAMIGO_DOMAIN}
|
FRONTEND_URL: ${BRIDGE_DOMAIN}
|
||||||
API_URL: "http://metamigo-api:3001"
|
API_URL: "http://bridge-api:3001"
|
||||||
NEXTAUTH_URL: ${METAMIGO_DOMAIN}
|
NEXTAUTH_URL: ${BRIDGE_DOMAIN}
|
||||||
NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
|
NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
|
||||||
NEXTAUTH_AUDIENCE: ${NEXTAUTH_AUDIENCE}
|
NEXTAUTH_AUDIENCE: ${NEXTAUTH_AUDIENCE}
|
||||||
NEXTAUTH_SIGNING_KEY_B64: ${NEXTAUTH_SIGNING_KEY_B64}
|
NEXTAUTH_SIGNING_KEY_B64: ${NEXTAUTH_SIGNING_KEY_B64}
|
||||||
|
|
@ -55,7 +55,7 @@ services:
|
||||||
[
|
[
|
||||||
*common-global-variables,
|
*common-global-variables,
|
||||||
*common-zammad-variables,
|
*common-zammad-variables,
|
||||||
*common-metamigo-variables,
|
*common-bridge-variables,
|
||||||
]
|
]
|
||||||
POSTGRES_USER: zammad
|
POSTGRES_USER: zammad
|
||||||
POSTGRES_PASSWORD: ${ZAMMAD_DATABASE_PASSWORD}
|
POSTGRES_PASSWORD: ${ZAMMAD_DATABASE_PASSWORD}
|
||||||
|
|
@ -68,13 +68,13 @@ services:
|
||||||
- postgresql-data:/var/lib/postgresql/data
|
- postgresql-data:/var/lib/postgresql/data
|
||||||
|
|
||||||
# volumes:
|
# volumes:
|
||||||
# - metamigo-data:/var/lib/postgresql/data
|
# - bridge-data:/var/lib/postgresql/data
|
||||||
# - ./scripts/bootstrap-metamigo.sh:/docker-entrypoint-initdb.d/bootstrap-metamigo.sh
|
# - ./scripts/bootstrap-bridge.sh:/docker-entrypoint-initdb.d/bootstrap-bridge.sh
|
||||||
#environment:
|
#environment:
|
||||||
# <<: *common-metamigo-variables
|
# <<: *common-bridge-variables
|
||||||
# POSTGRES_PASSWORD: ${METAMIGO_DATABASE_ROOT_PASSWORD}
|
# POSTGRES_PASSWORD: ${BRIDGE_DATABASE_ROOT_PASSWORD}
|
||||||
# POSTGRES_USER: "root"
|
# POSTGRES_USER: "root"
|
||||||
# POSTGRES_DB: "metamigo"
|
# POSTGRES_DB: "bridge"
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
postgresql-data:
|
postgresql-data:
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,14 @@ const app = process.argv[2];
|
||||||
const command = process.argv[3];
|
const command = process.argv[3];
|
||||||
|
|
||||||
const files = {
|
const files = {
|
||||||
all: ["zammad", "postgresql", "metamigo", "opensearch", "leafcutter", "link"],
|
all: ["zammad", "postgresql", "bridge", "opensearch", "leafcutter", "link"],
|
||||||
linkDev: ["zammad", "postgresql", "opensearch"],
|
linkDev: ["zammad", "postgresql", "opensearch"],
|
||||||
link: ["zammad", "postgresql", "opensearch", "link"],
|
link: ["zammad", "postgresql", "opensearch", "link"],
|
||||||
leafcutterDev: ["opensearch"],
|
leafcutterDev: ["opensearch"],
|
||||||
leafcutter: ["opensearch", "leafcutter"],
|
leafcutter: ["opensearch", "leafcutter"],
|
||||||
opensearch: ["opensearch"],
|
opensearch: ["opensearch"],
|
||||||
metamigoDev: ["zammad", "postgresql"],
|
bridgeDev: ["zammad", "postgresql"],
|
||||||
metamigo: ["zammad", "postgresql", "metamigo"],
|
bridge: ["zammad", "postgresql", "bridge"],
|
||||||
zammad: ["zammad", "postgresql", "opensearch"],
|
zammad: ["zammad", "postgresql", "opensearch"],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# uninstall
|
# uninstall
|
||||||
package_names = %w[Hardening Leafcutter Metamigo]
|
package_names = %w[Hardening Leafcutter Bridge]
|
||||||
|
|
||||||
package_names.each do |name|
|
package_names.each do |name|
|
||||||
puts "Attempting to uninstall #{name} package..."
|
puts "Attempting to uninstall #{name} package..."
|
||||||
|
|
|
||||||
16316
package-lock.json
generated
16316
package-lock.json
generated
File diff suppressed because it is too large
Load diff
12
package.json
12
package.json
|
|
@ -9,7 +9,7 @@
|
||||||
"fmt": "turbo run fmt",
|
"fmt": "turbo run fmt",
|
||||||
"upgrade:setup": "npm i -g npm-check-updates",
|
"upgrade:setup": "npm i -g npm-check-updates",
|
||||||
"upgrade:check": "ncu && ncu -ws",
|
"upgrade:check": "ncu && ncu -ws",
|
||||||
"upgrade:all": "ncu -u && ncu -ws -u && npm i",
|
"upgrade:all": "ncu -u -x eslint && ncu -ws -u -x eslint && npm i",
|
||||||
"clean": "rm -f package-lock.json && rm -rf node_modules && rm -rf apps/*/node_modules && rm -rf packages/*/node_modules && rm -rf apps/*/.next && rm -rf packages/*/.turbo && rm -rf apps/*/.turbo && rm -rf docker/zammad/addons/*",
|
"clean": "rm -f package-lock.json && rm -rf node_modules && rm -rf apps/*/node_modules && rm -rf packages/*/node_modules && rm -rf apps/*/.next && rm -rf packages/*/.turbo && rm -rf apps/*/.turbo && rm -rf docker/zammad/addons/*",
|
||||||
"docker:all:up": "node docker/scripts/docker.js all up",
|
"docker:all:up": "node docker/scripts/docker.js all up",
|
||||||
"docker:all:down": "node docker/scripts/docker.js all down",
|
"docker:all:down": "node docker/scripts/docker.js all down",
|
||||||
|
|
@ -30,11 +30,11 @@
|
||||||
"docker:zammad:up": "node docker/scripts/docker.js zammad up",
|
"docker:zammad:up": "node docker/scripts/docker.js zammad up",
|
||||||
"docker:zammad:down": "node docker/scripts/docker.js zammad down",
|
"docker:zammad:down": "node docker/scripts/docker.js zammad down",
|
||||||
"docker:zammad:build": "node docker/scripts/docker.js zammad build",
|
"docker:zammad:build": "node docker/scripts/docker.js zammad build",
|
||||||
"docker:metamigo:dev:up": "node docker/scripts/docker.js metamigoDev up",
|
"docker:bridge:dev:up": "node docker/scripts/docker.js bridgeDev up",
|
||||||
"docker:metamigo:dev:down": "node docker/scripts/docker.js metamigoDev down",
|
"docker:bridge:dev:down": "node docker/scripts/docker.js bridgeDev down",
|
||||||
"docker:metamigo:up": "node docker/scripts/docker.js metamigo up",
|
"docker:bridge:up": "node docker/scripts/docker.js bridge up",
|
||||||
"docker:metamigo:down": "node docker/scripts/docker.js metamigo down",
|
"docker:bridge:down": "node docker/scripts/docker.js bridge down",
|
||||||
"docker:metamigo:build": "node docker/scripts/docker.js metamigo build"
|
"docker:bridge:build": "node docker/scripts/docker.js bridge build"
|
||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"apps/*",
|
"apps/*",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "metamigo-ui",
|
"name": "bridge-ui",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
|
|
@ -9,12 +9,12 @@
|
||||||
"fmt": "prettier \"profile/**/*.js\" --write"
|
"fmt": "prettier \"profile/**/*.js\" --write"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@rushstack/eslint-patch": "^1.10.1",
|
"@rushstack/eslint-patch": "^1.10.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.6.0",
|
"@typescript-eslint/eslint-plugin": "^7.7.0",
|
||||||
"@typescript-eslint/parser": "^7.6.0",
|
"@typescript-eslint/parser": "^7.7.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-config-xo-space": "^0.35.0",
|
"eslint-config-xo-space": "^0.35.0",
|
||||||
"eslint-plugin-cypress": "^2.15.1",
|
"eslint-plugin-cypress": "^2.15.2",
|
||||||
"eslint-plugin-eslint-comments": "^3.2.0",
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.29.1",
|
||||||
"eslint-plugin-jest": "^28.2.0",
|
"eslint-plugin-jest": "^28.2.0",
|
||||||
|
|
@ -24,12 +24,12 @@
|
||||||
"@babel/eslint-parser": "7.24.1"
|
"@babel/eslint-parser": "7.24.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"eslint": "^7.32.0",
|
"eslint": "^8",
|
||||||
"typescript": "^4.9.5"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^9.0.0",
|
"eslint": "^8",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"typescript": "^5.4.4"
|
"typescript": "^5.4.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,12 @@
|
||||||
"@mui/icons-material": "^5",
|
"@mui/icons-material": "^5",
|
||||||
"@mui/lab": "^5.0.0-alpha.170",
|
"@mui/lab": "^5.0.0-alpha.170",
|
||||||
"@mui/material": "^5",
|
"@mui/material": "^5",
|
||||||
"@mui/x-data-grid-pro": "^7.1.1",
|
"@mui/x-data-grid-pro": "^7.3.0",
|
||||||
"@mui/x-date-pickers-pro": "^7.1.1",
|
"@mui/x-date-pickers-pro": "^7.2.0",
|
||||||
"opensearch-common": "*",
|
"opensearch-common": "*",
|
||||||
"date-fns": "^3.6.0",
|
"date-fns": "^3.6.0",
|
||||||
"material-ui-popup-state": "^5.1.0",
|
"material-ui-popup-state": "^5.1.0",
|
||||||
"next": "14.1.4",
|
"next": "14.2.2",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-cookie": "^7.1.4",
|
"react-cookie": "^7.1.4",
|
||||||
"react-cookie-consent": "^9.0.0",
|
"react-cookie-consent": "^9.0.0",
|
||||||
|
|
@ -30,18 +30,18 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.24.4",
|
"@babel/core": "^7.24.4",
|
||||||
"@types/node": "^20.12.6",
|
"@types/node": "^20.12.7",
|
||||||
"@types/react": "18.2.75",
|
"@types/react": "18.2.79",
|
||||||
"@types/uuid": "^9.0.8",
|
"@types/uuid": "^9.0.8",
|
||||||
"babel-loader": "^9.1.3",
|
"babel-loader": "^9.1.3",
|
||||||
"eslint": "^9.0.0",
|
"eslint": "^8.0.0",
|
||||||
"eslint-config-next": "^14.1.4",
|
"eslint-config-next": "^14.2.2",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.29.1",
|
||||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
"eslint-plugin-react": "^7.34.1",
|
"eslint-plugin-react": "^7.34.1",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"typescript": "5.4.4"
|
"typescript": "5.4.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,23 +5,23 @@
|
||||||
"build": "tsc -p tsconfig.json"
|
"build": "tsc -p tsconfig.json"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opensearch-project/opensearch": "^2.6.0",
|
"@opensearch-project/opensearch": "^2.7.0",
|
||||||
"uuid": "^9.0.1"
|
"uuid": "^9.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.24.4",
|
"@babel/core": "^7.24.4",
|
||||||
"@types/node": "^20.12.6",
|
"@types/node": "^20.12.7",
|
||||||
"@types/react": "18.2.75",
|
"@types/react": "18.2.79",
|
||||||
"@types/uuid": "^9.0.8",
|
"@types/uuid": "^9.0.8",
|
||||||
"babel-loader": "^9.1.3",
|
"babel-loader": "^9.1.3",
|
||||||
"eslint": "^9.0.0",
|
"eslint": "^8.0.0",
|
||||||
"eslint-config-next": "^14.1.4",
|
"eslint-config-next": "^14.2.2",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.29.1",
|
||||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
"eslint-plugin-react": "^7.34.1",
|
"eslint-plugin-react": "^7.34.1",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"typescript": "5.4.4"
|
"typescript": "5.4.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -241,7 +241,7 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
|
||||||
fontFamily: poppins.style.fontFamily,
|
fontFamily: poppins.style.fontFamily,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Metamigo
|
CDR Bridge
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -11,15 +11,15 @@
|
||||||
"@mui/icons-material": "^5",
|
"@mui/icons-material": "^5",
|
||||||
"@mui/lab": "^5.0.0-alpha.170",
|
"@mui/lab": "^5.0.0-alpha.170",
|
||||||
"@mui/material": "^5",
|
"@mui/material": "^5",
|
||||||
"@mui/x-data-grid-pro": "^7.1.1",
|
"@mui/x-data-grid-pro": "^7.3.0",
|
||||||
"@mui/x-date-pickers-pro": "^7.1.1",
|
"@mui/x-date-pickers-pro": "^7.2.0",
|
||||||
"next": "14.1.4",
|
"next": "14.2.2",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0"
|
"react-dom": "18.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.12.6",
|
"@types/node": "^20.12.7",
|
||||||
"@types/react": "18.2.75",
|
"@types/react": "18.2.79",
|
||||||
"typescript": "^5.4.4"
|
"typescript": "^5.4.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue