feat: Passwordless cross-device authentication

- Arkitektur: docs/auth/passwordless-architecture.md
- Backend: iom/quixzoom-auth-service/ (FastAPI + Redis)
- Webb: quixzoom-market-pages/se/login/ (QR-kod + polling)
- App: iom/quixzoom-app/src/features/auth/ (push + deep links)

Flöde: QR-kod → app-godkännande → webb-inloggad
This commit is contained in:
Bernt
2026-07-07 07:11:50 +00:00
parent 4aa984ad74
commit 6989a98d75
61843 changed files with 5491611 additions and 872231 deletions
+5
View File
@@ -0,0 +1,5 @@
/// <reference types="react" />
import { Api } from '../services/Api';
export declare const App: ({ api }: {
api: Api;
}) => JSX.Element;
+37
View File
@@ -0,0 +1,37 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.App = void 0;
const react_1 = __importDefault(require("react"));
const react_router_dom_1 = require("react-router-dom");
const react_toastify_1 = require("react-toastify");
const useScrollTopOnNav_1 = require("../hooks/useScrollTopOnNav");
const useStore_1 = require("../hooks/useStore");
const Header_1 = require("./Header/Header");
const Menu_1 = require("./Menu/Menu");
const QueuePage_1 = require("./QueuePage/QueuePage");
const RedisStats_1 = require("./RedisStats/RedisStats");
const App = ({ api }) => {
var _a, _b, _c, _d, _e;
useScrollTopOnNav_1.useScrollTopOnNav();
const { state, actions, selectedStatuses } = useStore_1.useStore(api);
return (react_1.default.createElement(react_1.default.Fragment, null,
react_1.default.createElement(Header_1.Header, null, ((_a = state.data) === null || _a === void 0 ? void 0 : _a.stats) && react_1.default.createElement(RedisStats_1.RedisStats, { stats: (_b = state.data) === null || _b === void 0 ? void 0 : _b.stats })),
react_1.default.createElement("main", null,
react_1.default.createElement("div", null, state.loading ? ('Loading...') : (react_1.default.createElement(react_router_dom_1.Switch, null,
react_1.default.createElement(react_router_dom_1.Route, { path: "/queue/:name", render: ({ match: { params } }) => {
var _a;
const currentQueueName = decodeURIComponent(params.name);
const queue = (_a = state.data) === null || _a === void 0 ? void 0 : _a.queues.find((q) => q.name === currentQueueName);
return (react_1.default.createElement(QueuePage_1.QueuePage, { queue: queue, actions: actions, selectedStatus: selectedStatuses }));
} }),
react_1.default.createElement(react_router_dom_1.Route, { path: "/", exact: true }, !!state.data &&
Array.isArray((_c = state.data) === null || _c === void 0 ? void 0 : _c.queues) &&
state.data.queues.length > 0 && (react_1.default.createElement(react_router_dom_1.Redirect, { to: `/queue/${encodeURIComponent((_d = state.data) === null || _d === void 0 ? void 0 : _d.queues[0].name)}` }))))))),
react_1.default.createElement(Menu_1.Menu, { queues: (_e = state.data) === null || _e === void 0 ? void 0 : _e.queues.map((q) => q.name), selectedStatuses: selectedStatuses }),
react_1.default.createElement(react_toastify_1.ToastContainer, null)));
};
exports.App = App;
//# sourceMappingURL=App.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"App.js","sourceRoot":"","sources":["../../../src/ui/components/App.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AACzB,uDAA0D;AAC1D,mDAA+C;AAC/C,kEAA8D;AAC9D,gDAA4C;AAE5C,4CAAwC;AACxC,sCAAkC;AAClC,qDAAiD;AACjD,wDAAoD;AAE7C,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,EAAgB,EAAE,EAAE;;IAC3C,qCAAiB,EAAE,CAAA;IACnB,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,mBAAQ,CAAC,GAAG,CAAC,CAAA;IAE1D,OAAO,CACL;QACE,8BAAC,eAAM,QACJ,CAAA,MAAA,KAAK,CAAC,IAAI,0CAAE,KAAK,KAAI,8BAAC,uBAAU,IAAC,KAAK,EAAE,MAAA,KAAK,CAAC,IAAI,0CAAE,KAAK,GAAI,CACvD;QACT;YACE,2CACG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CACf,YAAY,CACb,CAAC,CAAC,CAAC,CACF,8BAAC,yBAAM;gBACL,8BAAC,wBAAK,IACJ,IAAI,EAAC,cAAc,EACnB,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE;;wBAChC,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;wBACxD,MAAM,KAAK,GAAG,MAAA,KAAK,CAAC,IAAI,0CAAE,MAAM,CAAC,IAAI,CACnC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,CACnC,CAAA;wBAED,OAAO,CACL,8BAAC,qBAAS,IACR,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,gBAAgB,GAChC,CACH,CAAA;oBACH,CAAC,GACD;gBAEF,8BAAC,wBAAK,IAAC,IAAI,EAAC,GAAG,EAAC,KAAK,UAClB,CAAC,CAAC,KAAK,CAAC,IAAI;oBACX,KAAK,CAAC,OAAO,CAAC,MAAA,KAAK,CAAC,IAAI,0CAAE,MAAM,CAAC;oBACjC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,CAC9B,8BAAC,2BAAQ,IACP,EAAE,EAAE,UAAU,kBAAkB,CAC9B,MAAA,KAAK,CAAC,IAAI,0CAAE,MAAM,CAAC,CAAC,EAAE,IAAI,CAC3B,EAAE,GACH,CACH,CACG,CACD,CACV,CACG,CACD;QACP,8BAAC,WAAI,IACH,MAAM,EAAE,MAAA,KAAK,CAAC,IAAI,0CAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAC7C,gBAAgB,EAAE,gBAAgB,GAClC;QACF,8BAAC,+BAAc,OAAG,CACjB,CACJ,CAAA;AACH,CAAC,CAAA;AAvDY,QAAA,GAAG,OAuDf"}
@@ -0,0 +1,2 @@
import { PropsWithChildren } from 'react';
export declare const Header: ({ children }: PropsWithChildren<any>) => JSX.Element;
+15
View File
@@ -0,0 +1,15 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Header = void 0;
const react_1 = __importDefault(require("react"));
const Header_module_css_1 = __importDefault(require("./Header.module.css"));
const Header = ({ children }) => {
return (react_1.default.createElement("header", { className: Header_module_css_1.default.header },
react_1.default.createElement("div", { className: Header_module_css_1.default.logo }, "\uD83C\uDFAF Bull Dashboard"),
children));
};
exports.Header = Header;
//# sourceMappingURL=Header.js.map
@@ -0,0 +1 @@
{"version":3,"file":"Header.js","sourceRoot":"","sources":["../../../../src/ui/components/Header/Header.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAgD;AAChD,4EAAmC;AAE5B,MAAM,MAAM,GAAG,CAAC,EAAE,QAAQ,EAA0B,EAAE,EAAE;IAC7D,OAAO,CACL,0CAAQ,SAAS,EAAE,2BAAC,CAAC,MAAM;QACzB,uCAAK,SAAS,EAAE,2BAAC,CAAC,IAAI,kCAAyB;QAC9C,QAAQ,CACF,CACV,CAAA;AACH,CAAC,CAAA;AAPY,QAAA,MAAM,UAOlB"}
@@ -0,0 +1,14 @@
import React from 'react';
interface HighlightProps {
language: 'json' | 'stacktrace';
children: string | null;
}
export declare class Highlight extends React.Component<HighlightProps> {
private codeRef;
shouldComponentUpdate(nextProps: Readonly<HighlightProps>): boolean;
componentDidMount(): void;
componentDidUpdate(): void;
render(): JSX.Element;
private highlightCode;
}
export {};
@@ -0,0 +1,49 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Highlight = void 0;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const core_1 = __importDefault(require("highlight.js/lib/core"));
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const json_1 = __importDefault(require("highlight.js/lib/languages/json"));
const react_1 = __importDefault(require("react"));
const stacktrace_1 = require("./languages/stacktrace");
core_1.default.registerLanguage('json', json_1.default);
core_1.default.registerLanguage('stacktrace', stacktrace_1.stacktraceJS);
class Highlight extends react_1.default.Component {
constructor() {
super(...arguments);
this.codeRef = react_1.default.createRef();
}
shouldComponentUpdate(nextProps) {
return (nextProps.language !== this.props.language ||
(Array.isArray(this.props.children)
? this.props.children.some((item) => ![].concat(nextProps.children).includes(item))
: nextProps.children !== this.props.children));
}
componentDidMount() {
this.highlightCode();
}
componentDidUpdate() {
this.highlightCode();
}
render() {
const { language } = this.props;
return (react_1.default.createElement("pre", { ref: this.codeRef },
react_1.default.createElement("code", { className: language })));
}
highlightCode() {
var _a;
const node = (_a = this.codeRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('code');
if (node) {
node.textContent = this.props.children;
core_1.default.highlightElement(node);
}
}
}
exports.Highlight = Highlight;
//# sourceMappingURL=Highlight.js.map
@@ -0,0 +1 @@
{"version":3,"file":"Highlight.js","sourceRoot":"","sources":["../../../../src/ui/components/Highlight/Highlight.tsx"],"names":[],"mappings":";;;;;;AAAA,6DAA6D;AAC7D,aAAa;AACb,iEAAwC;AACxC,6DAA6D;AAC7D,aAAa;AACb,2EAAkD;AAClD,kDAAyB;AACzB,uDAAqD;AAErD,cAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,cAAI,CAAC,CAAA;AACnC,cAAI,CAAC,gBAAgB,CAAC,YAAY,EAAE,yBAAY,CAAC,CAAA;AAOjD,MAAa,SAAU,SAAQ,eAAK,CAAC,SAAyB;IAA9D;;QACU,YAAO,GAAG,eAAK,CAAC,SAAS,EAAkB,CAAA;IAsCrD,CAAC;IApCQ,qBAAqB,CAAC,SAAmC;QAC9D,OAAO,CACL,SAAS,CAAC,QAAQ,KAAK,IAAI,CAAC,KAAK,CAAC,QAAQ;YAC1C,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;gBACjC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CACtB,CAAC,IAAS,EAAE,EAAE,CACZ,CAAE,EAAU,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CACzD;gBACH,CAAC,CAAC,SAAS,CAAC,QAAQ,KAAK,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAChD,CAAA;IACH,CAAC;IAEM,iBAAiB;QACtB,IAAI,CAAC,aAAa,EAAE,CAAA;IACtB,CAAC;IAEM,kBAAkB;QACvB,IAAI,CAAC,aAAa,EAAE,CAAA;IACtB,CAAC;IAEM,MAAM;QACX,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,KAAK,CAAA;QAC/B,OAAO,CACL,uCAAK,GAAG,EAAE,IAAI,CAAC,OAAO;YACpB,wCAAM,SAAS,EAAE,QAAQ,GAAI,CACzB,CACP,CAAA;IACH,CAAC;IAEO,aAAa;;QACnB,MAAM,IAAI,GAAG,MAAA,IAAI,CAAC,OAAO,CAAC,OAAO,0CAAE,aAAa,CAAC,MAAM,CAAC,CAAA;QACxD,IAAI,IAAI,EAAE;YACR,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAA;YACtC,cAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAA;SAC5B;IACH,CAAC;CACF;AAvCD,8BAuCC"}
@@ -0,0 +1 @@
export declare function stacktraceJS(): any;
@@ -0,0 +1,51 @@
"use strict";
/*
Language: StacktraceJS
Author: FelixMosh
Description: Node stacktrace highlighter
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.stacktraceJS = void 0;
function stacktraceJS() {
const ERROR = {
className: 'type',
begin: /^\w*Error:\s*/,
relevance: 40,
contains: [
{
className: 'title',
begin: /.*/,
end: /$/,
excludeStart: true,
endsWithParent: true,
},
],
};
const LINE_NUMBER = {
className: 'number',
begin: ':\\d+:\\d+',
relevance: 5,
};
const TRACE_LINE = {
className: 'trace-line',
begin: /^\s*at/,
end: /$/,
keywords: 'at as async prototype anonymous function',
contains: [
{
className: 'code-path',
begin: /\(/,
end: /\)$/,
excludeEnd: true,
excludeBegin: true,
contains: [LINE_NUMBER],
},
],
};
return {
case_insensitive: true,
contains: [ERROR, TRACE_LINE, LINE_NUMBER],
};
}
exports.stacktraceJS = stacktraceJS;
//# sourceMappingURL=stacktrace.js.map
@@ -0,0 +1 @@
{"version":3,"file":"stacktrace.js","sourceRoot":"","sources":["../../../../../src/ui/components/Highlight/languages/stacktrace.ts"],"names":[],"mappings":";AAAA;;;;EAIE;;;AAEF,SAAgB,YAAY;IAC1B,MAAM,KAAK,GAAG;QACZ,SAAS,EAAE,MAAM;QACjB,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,EAAE;QACb,QAAQ,EAAE;YACR;gBACE,SAAS,EAAE,OAAO;gBAClB,KAAK,EAAE,IAAI;gBACX,GAAG,EAAE,GAAG;gBACR,YAAY,EAAE,IAAI;gBAClB,cAAc,EAAE,IAAI;aACrB;SACF;KACF,CAAA;IAED,MAAM,WAAW,GAAG;QAClB,SAAS,EAAE,QAAQ;QACnB,KAAK,EAAE,YAAY;QACnB,SAAS,EAAE,CAAC;KACb,CAAA;IAED,MAAM,UAAU,GAAG;QACjB,SAAS,EAAE,YAAY;QACvB,KAAK,EAAE,QAAQ;QACf,GAAG,EAAE,GAAG;QACR,QAAQ,EAAE,0CAA0C;QACpD,QAAQ,EAAE;YACR;gBACE,SAAS,EAAE,WAAW;gBACtB,KAAK,EAAE,IAAI;gBACX,GAAG,EAAE,KAAK;gBACV,UAAU,EAAE,IAAI;gBAChB,YAAY,EAAE,IAAI;gBAClB,QAAQ,EAAE,CAAC,WAAW,CAAC;aACxB;SACF;KACF,CAAA;IAED,OAAO;QACL,gBAAgB,EAAE,IAAI;QACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC;KAC3C,CAAA;AACH,CAAC;AA3CD,oCA2CC"}
@@ -0,0 +1,2 @@
/// <reference types="react" />
export declare const PromoteIcon: () => JSX.Element;
+11
View File
@@ -0,0 +1,11 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PromoteIcon = void 0;
const react_1 = __importDefault(require("react"));
const PromoteIcon = () => (react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20" },
react_1.default.createElement("path", { d: "M15 17v-2.99A4 4 0 0 0 11 10H8v5L2 9l6-6v5h3a6 6 0 0 1 6 6v3h-2z" })));
exports.PromoteIcon = PromoteIcon;
//# sourceMappingURL=Promote.js.map
@@ -0,0 +1 @@
{"version":3,"file":"Promote.js","sourceRoot":"","sources":["../../../../src/ui/components/Icons/Promote.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AAElB,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,CAC/B,uCAAK,KAAK,EAAC,4BAA4B,EAAC,OAAO,EAAC,WAAW;IACzD,wCAAM,CAAC,EAAC,kEAAkE,GAAG,CACzE,CACP,CAAA;AAJY,QAAA,WAAW,eAIvB"}
+2
View File
@@ -0,0 +1,2 @@
/// <reference types="react" />
export declare const RetryIcon: () => JSX.Element;
+11
View File
@@ -0,0 +1,11 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RetryIcon = void 0;
const react_1 = __importDefault(require("react"));
const RetryIcon = () => (react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20" },
react_1.default.createElement("path", { d: "M5 4a2 2 0 0 0-2 2v6H0l4 4 4-4H5V6h7l2-2H5zm10 4h-3l4-4 4 4h-3v6a2 2 0 0 1-2 2H6l2-2h7V8z" })));
exports.RetryIcon = RetryIcon;
//# sourceMappingURL=Retry.js.map
@@ -0,0 +1 @@
{"version":3,"file":"Retry.js","sourceRoot":"","sources":["../../../../src/ui/components/Icons/Retry.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AAElB,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,CAC7B,uCAAK,KAAK,EAAC,4BAA4B,EAAC,OAAO,EAAC,WAAW;IACzD,wCAAM,CAAC,EAAC,2FAA2F,GAAG,CAClG,CACP,CAAA;AAJY,QAAA,SAAS,aAIrB"}
+2
View File
@@ -0,0 +1,2 @@
/// <reference types="react" />
export declare const TrashIcon: () => JSX.Element;
+11
View File
@@ -0,0 +1,11 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TrashIcon = void 0;
const react_1 = __importDefault(require("react"));
const TrashIcon = () => (react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20" },
react_1.default.createElement("path", { d: "M6 2l2-2h4l2 2h4v2H2V2h4zM3 6h14l-1 14H4L3 6zm5 2v10h1V8H8zm3 0v10h1V8h-1z" })));
exports.TrashIcon = TrashIcon;
//# sourceMappingURL=Trash.js.map
@@ -0,0 +1 @@
{"version":3,"file":"Trash.js","sourceRoot":"","sources":["../../../../src/ui/components/Icons/Trash.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AAElB,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,CAC7B,uCAAK,KAAK,EAAC,4BAA4B,EAAC,OAAO,EAAC,WAAW;IACzD,wCAAM,CAAC,EAAC,4EAA4E,GAAG,CACnF,CACP,CAAA;AAJY,QAAA,SAAS,aAIrB"}
@@ -0,0 +1,4 @@
import React from 'react';
export declare const Button: ({ children, className, isActive, ...rest }: React.ClassAttributes<HTMLButtonElement> & React.ButtonHTMLAttributes<HTMLButtonElement> & {
isActive?: boolean | undefined;
}) => JSX.Element;
@@ -0,0 +1,12 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Button = void 0;
const react_1 = __importDefault(require("react"));
const Button_module_css_1 = __importDefault(require("./Button.module.css"));
const classnames_1 = __importDefault(require("classnames"));
const Button = ({ children, className, isActive = false, ...rest }) => (react_1.default.createElement("button", Object.assign({ type: "button" }, rest, { className: classnames_1.default(Button_module_css_1.default.button, className, { [Button_module_css_1.default.isActive]: isActive }) }), children));
exports.Button = Button;
//# sourceMappingURL=Button.js.map
@@ -0,0 +1 @@
{"version":3,"file":"Button.js","sourceRoot":"","sources":["../../../../../src/ui/components/JobCard/Button/Button.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AACzB,4EAAmC;AACnC,4DAA2B;AAEpB,MAAM,MAAM,GAAG,CAAC,EACrB,QAAQ,EACR,SAAS,EACT,QAAQ,GAAG,KAAK,EAChB,GAAG,IAAI,EAIiB,EAAE,EAAE,CAAC,CAC7B,wDACE,IAAI,EAAC,QAAQ,IACT,IAAI,IACR,SAAS,EAAE,oBAAE,CAAC,2BAAC,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,2BAAC,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC,KAE7D,QAAQ,CACF,CACV,CAAA;AAhBY,QAAA,MAAM,UAgBlB"}
@@ -0,0 +1,12 @@
/// <reference types="react" />
import { AppJob } from '../../../../@types/app';
import { Status } from '../../constants';
interface DetailsProps {
job: AppJob;
status: Status;
actions: {
getJobLogs: () => Promise<string[]>;
};
}
export declare const Details: ({ status, job, actions }: DetailsProps) => JSX.Element | null;
export {};
@@ -0,0 +1,25 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Details = void 0;
const react_1 = __importDefault(require("react"));
const useDetailsTabs_1 = require("../../../hooks/useDetailsTabs");
const Button_1 = require("../Button/Button");
const Details_module_css_1 = __importDefault(require("./Details.module.css"));
const DetailsContent_1 = require("./DetailsContent/DetailsContent");
const Details = ({ status, job, actions }) => {
const { tabs, selectedTab } = useDetailsTabs_1.useDetailsTabs(status);
if (tabs.length === 0) {
return null;
}
return (react_1.default.createElement("div", { className: Details_module_css_1.default.details },
react_1.default.createElement("ul", { className: Details_module_css_1.default.tabActions }, tabs.map((tab) => (react_1.default.createElement("li", { key: tab.title },
react_1.default.createElement(Button_1.Button, { onClick: tab.selectTab, isActive: tab.isActive }, tab.title))))),
react_1.default.createElement("div", { className: Details_module_css_1.default.tabContent },
react_1.default.createElement("div", null,
react_1.default.createElement(DetailsContent_1.DetailsContent, { selectedTab: selectedTab, job: job, actions: actions })))));
};
exports.Details = Details;
//# sourceMappingURL=Details.js.map
@@ -0,0 +1 @@
{"version":3,"file":"Details.js","sourceRoot":"","sources":["../../../../../src/ui/components/JobCard/Details/Details.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AAEzB,kEAA8D;AAE9D,6CAAyC;AACzC,8EAAoC;AACpC,oEAAgE;AAQzD,MAAM,OAAO,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAgB,EAAE,EAAE;IAChE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,+BAAc,CAAC,MAAM,CAAC,CAAA;IAEpD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;QACrB,OAAO,IAAI,CAAA;KACZ;IAED,OAAO,CACL,uCAAK,SAAS,EAAE,4BAAC,CAAC,OAAO;QACvB,sCAAI,SAAS,EAAE,4BAAC,CAAC,UAAU,IACxB,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACjB,sCAAI,GAAG,EAAE,GAAG,CAAC,KAAK;YAChB,8BAAC,eAAM,IAAC,OAAO,EAAE,GAAG,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,IACnD,GAAG,CAAC,KAAK,CACH,CACN,CACN,CAAC,CACC;QACL,uCAAK,SAAS,EAAE,4BAAC,CAAC,UAAU;YAC1B;gBACE,8BAAC,+BAAc,IACb,WAAW,EAAE,WAAW,EACxB,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,OAAO,GAChB,CACE,CACF,CACF,CACP,CAAA;AACH,CAAC,CAAA;AA7BY,QAAA,OAAO,WA6BnB"}
@@ -0,0 +1,12 @@
/// <reference types="react" />
import { AppJob } from '../../../../../@types/app';
import { TabsType } from '../../../../hooks/useDetailsTabs';
interface DetailsContentProps {
job: AppJob;
selectedTab: TabsType;
actions: {
getJobLogs: () => Promise<string[]>;
};
}
export declare const DetailsContent: ({ selectedTab, job: { stacktrace, data, returnValue, opts, failedReason }, actions, }: DetailsContentProps) => JSX.Element | null;
export {};
@@ -0,0 +1,25 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DetailsContent = void 0;
const react_1 = __importDefault(require("react"));
const Highlight_1 = require("../../../Highlight/Highlight");
const JobLogs_1 = require("./JobLogs/JobLogs");
const DetailsContent = ({ selectedTab, job: { stacktrace, data, returnValue, opts, failedReason }, actions, }) => {
switch (selectedTab) {
case 'Data':
return (react_1.default.createElement(Highlight_1.Highlight, { language: "json" }, JSON.stringify({ data, returnValue }, null, 2)));
case 'Options':
return (react_1.default.createElement(Highlight_1.Highlight, { language: "json" }, JSON.stringify(opts, null, 2)));
case 'Error':
return (react_1.default.createElement(react_1.default.Fragment, null, stacktrace.length === 0 ? (react_1.default.createElement("div", { className: "error" }, !!failedReason ? failedReason : 'NA')) : (react_1.default.createElement(Highlight_1.Highlight, { language: "stacktrace", key: "stacktrace" }, stacktrace.join('\n')))));
case 'Logs':
return react_1.default.createElement(JobLogs_1.JobLogs, { actions: actions });
default:
return null;
}
};
exports.DetailsContent = DetailsContent;
//# sourceMappingURL=DetailsContent.js.map
@@ -0,0 +1 @@
{"version":3,"file":"DetailsContent.js","sourceRoot":"","sources":["../../../../../../src/ui/components/JobCard/Details/DetailsContent/DetailsContent.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AAGzB,4DAAwD;AACxD,+CAA2C;AAUpC,MAAM,cAAc,GAAG,CAAC,EAC7B,WAAW,EACX,GAAG,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE,EAC1D,OAAO,GACa,EAAE,EAAE;IACxB,QAAQ,WAAW,EAAE;QACnB,KAAK,MAAM;YACT,OAAO,CACL,8BAAC,qBAAS,IAAC,QAAQ,EAAC,MAAM,IACvB,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CACrC,CACb,CAAA;QACH,KAAK,SAAS;YACZ,OAAO,CACL,8BAAC,qBAAS,IAAC,QAAQ,EAAC,MAAM,IAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAa,CACvE,CAAA;QACH,KAAK,OAAO;YACV,OAAO,CACL,8DACG,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CACzB,uCAAK,SAAS,EAAC,OAAO,IAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAO,CACpE,CAAC,CAAC,CAAC,CACF,8BAAC,qBAAS,IAAC,QAAQ,EAAC,YAAY,EAAC,GAAG,EAAC,YAAY,IAC9C,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CACZ,CACb,CACA,CACJ,CAAA;QACH,KAAK,MAAM;YACT,OAAO,8BAAC,iBAAO,IAAC,OAAO,EAAE,OAAO,GAAI,CAAA;QACtC;YACE,OAAO,IAAI,CAAA;KACd;AACH,CAAC,CAAA;AAjCY,QAAA,cAAc,kBAiC1B"}
@@ -0,0 +1,8 @@
/// <reference types="react" />
interface JobLogsProps {
actions: {
getJobLogs: () => Promise<string[]>;
};
}
export declare const JobLogs: ({ actions }: JobLogsProps) => JSX.Element | null;
export {};
@@ -0,0 +1,43 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.JobLogs = void 0;
const react_1 = __importStar(require("react"));
const JobLogs_module_css_1 = __importDefault(require("./JobLogs.module.css"));
const JobLogs = ({ actions }) => {
const [logs, setLogs] = react_1.useState([]);
react_1.useEffect(() => {
let mounted = true;
actions.getJobLogs().then((logs) => mounted && setLogs(logs));
return () => {
mounted = false;
};
}, []);
if (!Array.isArray(logs) || !logs.length) {
return null;
}
return (react_1.default.createElement("ul", { className: JobLogs_module_css_1.default.jobLogs }, logs.map((log, idx) => (react_1.default.createElement("li", { key: idx }, log)))));
};
exports.JobLogs = JobLogs;
//# sourceMappingURL=JobLogs.js.map
@@ -0,0 +1 @@
{"version":3,"file":"JobLogs.js","sourceRoot":"","sources":["../../../../../../../src/ui/components/JobCard/Details/DetailsContent/JobLogs/JobLogs.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAkD;AAClD,8EAAoC;AAQ7B,MAAM,OAAO,GAAG,CAAC,EAAE,OAAO,EAAgB,EAAE,EAAE;IACnD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,gBAAQ,CAAW,EAAE,CAAC,CAAA;IAE9C,iBAAS,CAAC,GAAG,EAAE;QACb,IAAI,OAAO,GAAG,IAAI,CAAA;QAClB,OAAO,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;QAC7D,OAAO,GAAG,EAAE;YACV,OAAO,GAAG,KAAK,CAAA;QACjB,CAAC,CAAA;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;QACxC,OAAO,IAAI,CAAA;KACZ;IAED,OAAO,CACL,sCAAI,SAAS,EAAE,4BAAC,CAAC,OAAO,IACrB,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CACtB,sCAAI,GAAG,EAAE,GAAG,IAAG,GAAG,CAAM,CACzB,CAAC,CACC,CACN,CAAA;AACH,CAAC,CAAA;AAtBY,QAAA,OAAO,WAsBnB"}
@@ -0,0 +1,12 @@
/// <reference types="react" />
import { Status } from '../../constants';
interface JobActionsProps {
status: Status;
actions: {
promoteJob: () => Promise<void>;
retryJob: () => Promise<void>;
cleanJob: () => Promise<void>;
};
}
export declare const JobActions: ({ actions, status }: JobActionsProps) => JSX.Element | null;
export {};
@@ -0,0 +1,37 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.JobActions = void 0;
const react_1 = __importDefault(require("react"));
const constants_1 = require("../../constants");
const Promote_1 = require("../../Icons/Promote");
const Retry_1 = require("../../Icons/Retry");
const Trash_1 = require("../../Icons/Trash");
const Tooltip_1 = require("../../Tooltip/Tooltip");
const Button_1 = require("../Button/Button");
const JobActions_module_css_1 = __importDefault(require("./JobActions.module.css"));
const buttonTypes = {
promote: { title: 'Promote', Icon: Promote_1.PromoteIcon, actionKey: 'promoteJob' },
clean: { title: 'Clean', Icon: Trash_1.TrashIcon, actionKey: 'cleanJob' },
retry: { title: 'Retry', Icon: Retry_1.RetryIcon, actionKey: 'retryJob' },
};
const statusToButtonsMap = {
[constants_1.STATUSES.failed]: [buttonTypes.retry, buttonTypes.clean],
[constants_1.STATUSES.delayed]: [buttonTypes.promote, buttonTypes.clean],
[constants_1.STATUSES.completed]: [buttonTypes.clean],
[constants_1.STATUSES.waiting]: [buttonTypes.clean],
};
const JobActions = ({ actions, status }) => {
const buttons = statusToButtonsMap[status];
if (!buttons) {
return null;
}
return (react_1.default.createElement("ul", { className: JobActions_module_css_1.default.jobActions }, buttons.map((type) => (react_1.default.createElement("li", { key: type.title },
react_1.default.createElement(Tooltip_1.Tooltip, { title: type.title },
react_1.default.createElement(Button_1.Button, { onClick: actions[type.actionKey], className: JobActions_module_css_1.default.button },
react_1.default.createElement(type.Icon, null))))))));
};
exports.JobActions = JobActions;
//# sourceMappingURL=JobActions.js.map
@@ -0,0 +1 @@
{"version":3,"file":"JobActions.js","sourceRoot":"","sources":["../../../../../src/ui/components/JobCard/JobActions/JobActions.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AACzB,+CAAkD;AAClD,iDAAiD;AACjD,6CAA6C;AAC7C,6CAA6C;AAC7C,mDAA+C;AAC/C,6CAAyC;AACzC,oFAAuC;AAiBvC,MAAM,WAAW,GAA+B;IAC9C,OAAO,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,qBAAW,EAAE,SAAS,EAAE,YAAY,EAAE;IACzE,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,iBAAS,EAAE,SAAS,EAAE,UAAU,EAAE;IACjE,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,iBAAS,EAAE,SAAS,EAAE,UAAU,EAAE;CAClE,CAAA;AAED,MAAM,kBAAkB,GAAiC;IACvD,CAAC,oBAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC;IACzD,CAAC,oBAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC;IAC5D,CAAC,oBAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC;IACzC,CAAC,oBAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC;CACxC,CAAA;AAEM,MAAM,UAAU,GAAG,CAAC,EAAE,OAAO,EAAE,MAAM,EAAmB,EAAE,EAAE;IACjE,MAAM,OAAO,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAA;IAC1C,IAAI,CAAC,OAAO,EAAE;QACZ,OAAO,IAAI,CAAA;KACZ;IACD,OAAO,CACL,sCAAI,SAAS,EAAE,+BAAC,CAAC,UAAU,IACxB,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACrB,sCAAI,GAAG,EAAE,IAAI,CAAC,KAAK;QACjB,8BAAC,iBAAO,IAAC,KAAK,EAAE,IAAI,CAAC,KAAK;YACxB,8BAAC,eAAM,IAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,+BAAC,CAAC,MAAM;gBAC3D,8BAAC,IAAI,CAAC,IAAI,OAAG,CACN,CACD,CACP,CACN,CAAC,CACC,CACN,CAAA;AACH,CAAC,CAAA;AAlBY,QAAA,UAAU,cAkBtB"}
@@ -0,0 +1,16 @@
/// <reference types="react" />
import { AppJob } from '../../../@types/app';
import { Status } from '../constants';
interface JobCardProps {
job: AppJob;
status: Status;
readOnlyMode: boolean;
actions: {
promoteJob: () => Promise<void>;
retryJob: () => Promise<void>;
cleanJob: () => Promise<void>;
getJobLogs: () => Promise<string[]>;
};
}
export declare const JobCard: ({ job, status, actions, readOnlyMode, }: JobCardProps) => JSX.Element;
export {};
+31
View File
@@ -0,0 +1,31 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.JobCard = void 0;
const react_1 = __importDefault(require("react"));
const Details_1 = require("./Details/Details");
const JobActions_1 = require("./JobActions/JobActions");
const JobCard_module_css_1 = __importDefault(require("./JobCard.module.css"));
const Progress_1 = require("./Progress/Progress");
const Timeline_1 = require("./Timeline/Timeline");
const JobCard = ({ job, status, actions, readOnlyMode, }) => (react_1.default.createElement("div", { className: JobCard_module_css_1.default.card },
react_1.default.createElement("div", { className: JobCard_module_css_1.default.sideInfo },
react_1.default.createElement("span", { title: `#${job.id}` },
"#",
job.id),
react_1.default.createElement(Timeline_1.Timeline, { job: job, status: status })),
react_1.default.createElement("div", { className: JobCard_module_css_1.default.contentWrapper },
react_1.default.createElement("div", { className: JobCard_module_css_1.default.title },
react_1.default.createElement("h4", null,
job.name,
job.attempts > 0 && react_1.default.createElement("span", null,
"attempt #",
job.attempts + 1)),
!readOnlyMode && react_1.default.createElement(JobActions_1.JobActions, { status: status, actions: actions })),
react_1.default.createElement("div", { className: JobCard_module_css_1.default.content },
react_1.default.createElement(Details_1.Details, { status: status, job: job, actions: actions }),
typeof job.progress === 'number' && (react_1.default.createElement(Progress_1.Progress, { percentage: job.progress, status: status, className: JobCard_module_css_1.default.progress }))))));
exports.JobCard = JobCard;
//# sourceMappingURL=JobCard.js.map
@@ -0,0 +1 @@
{"version":3,"file":"JobCard.js","sourceRoot":"","sources":["../../../../src/ui/components/JobCard/JobCard.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AAGzB,+CAA2C;AAC3C,wDAAoD;AACpD,8EAAoC;AACpC,kDAA8C;AAC9C,kDAA8C;AAcvC,MAAM,OAAO,GAAG,CAAC,EACtB,GAAG,EACH,MAAM,EACN,OAAO,EACP,YAAY,GACC,EAAE,EAAE,CAAC,CAClB,uCAAK,SAAS,EAAE,4BAAC,CAAC,IAAI;IACpB,uCAAK,SAAS,EAAE,4BAAC,CAAC,QAAQ;QACxB,wCAAM,KAAK,EAAE,IAAI,GAAG,CAAC,EAAE,EAAE;;YAAI,GAAG,CAAC,EAAE,CAAQ;QAC3C,8BAAC,mBAAQ,IAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAI,CAClC;IACN,uCAAK,SAAS,EAAE,4BAAC,CAAC,cAAc;QAC9B,uCAAK,SAAS,EAAE,4BAAC,CAAC,KAAK;YACrB;gBACG,GAAG,CAAC,IAAI;gBACR,GAAG,CAAC,QAAQ,GAAG,CAAC,IAAI;;oBAAgB,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAQ,CAC1D;YACJ,CAAC,YAAY,IAAI,8BAAC,uBAAU,IAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAI,CAC9D;QACN,uCAAK,SAAS,EAAE,4BAAC,CAAC,OAAO;YACvB,8BAAC,iBAAO,IAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,GAAI;YACtD,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,CACnC,8BAAC,mBAAQ,IACP,UAAU,EAAE,GAAG,CAAC,QAAQ,EACxB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,4BAAC,CAAC,QAAQ,GACrB,CACH,CACG,CACF,CACF,CACP,CAAA;AA/BY,QAAA,OAAO,WA+BnB"}
@@ -0,0 +1,7 @@
/// <reference types="react" />
import { Status } from '../../constants';
export declare const Progress: ({ percentage, status, className, }: {
percentage: number;
status: Status;
className?: string | undefined;
}) => JSX.Element;
@@ -0,0 +1,19 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Progress = void 0;
const react_1 = __importDefault(require("react"));
const Progress_module_css_1 = __importDefault(require("./Progress.module.css"));
const classnames_1 = __importDefault(require("classnames"));
const Progress = ({ percentage, status, className, }) => {
return (react_1.default.createElement("svg", { className: classnames_1.default(Progress_module_css_1.default.progress, className), viewBox: "0 0 148 148" },
react_1.default.createElement("circle", { cx: "70", cy: "70", r: "70", fill: "none", stroke: "#EDF2F7", strokeWidth: "8", strokeLinecap: "round", style: { transform: 'translate(4px, 4px)' } }),
react_1.default.createElement("circle", { cx: "70", cy: "70", r: "70", fill: "none", stroke: status === 'failed' ? '#F56565' : '#48BB78', strokeWidth: "8", strokeLinecap: "round", strokeDasharray: "600", strokeDashoffset: 600 - ((600 - 160) * percentage) / 100, style: { transform: 'translate(4px, -4px) rotate(-90deg)' } }),
react_1.default.createElement("text", { textAnchor: "middle", x: "74", y: "88" },
percentage,
"%")));
};
exports.Progress = Progress;
//# sourceMappingURL=Progress.js.map
@@ -0,0 +1 @@
{"version":3,"file":"Progress.js","sourceRoot":"","sources":["../../../../../src/ui/components/JobCard/Progress/Progress.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AAEzB,gFAAqC;AACrC,4DAA2B;AAEpB,MAAM,QAAQ,GAAG,CAAC,EACvB,UAAU,EACV,MAAM,EACN,SAAS,GAKV,EAAE,EAAE;IACH,OAAO,CACL,uCAAK,SAAS,EAAE,oBAAE,CAAC,6BAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,OAAO,EAAC,aAAa;QAC9D,0CACE,EAAE,EAAC,IAAI,EACP,EAAE,EAAC,IAAI,EACP,CAAC,EAAC,IAAI,EACN,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,SAAS,EAChB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,KAAK,EAAE,EAAE,SAAS,EAAE,qBAAqB,EAAE,GACnC;QACV,0CACE,EAAE,EAAC,IAAI,EACP,EAAE,EAAC,IAAI,EACP,CAAC,EAAC,IAAI,EACN,IAAI,EAAC,MAAM,EACX,MAAM,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EACnD,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,eAAe,EAAC,KAAK,EACrB,gBAAgB,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,GAAG,EACxD,KAAK,EAAE,EAAE,SAAS,EAAE,qCAAqC,EAAE,GACnD;QACV,wCAAM,UAAU,EAAC,QAAQ,EAAC,CAAC,EAAC,IAAI,EAAC,CAAC,EAAC,IAAI;YACpC,UAAU;gBACN,CACH,CACP,CAAA;AACH,CAAC,CAAA;AAtCY,QAAA,QAAQ,YAsCpB"}
@@ -0,0 +1,7 @@
/// <reference types="react" />
import { AppJob } from '../../../../@types/app';
import { Status } from '../../constants';
export declare const Timeline: ({ job, status, }: {
job: AppJob;
status: Status;
}) => JSX.Element;
@@ -0,0 +1,45 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Timeline = void 0;
const date_fns_1 = require("date-fns");
const react_1 = __importDefault(require("react"));
const Timeline_module_css_1 = __importDefault(require("./Timeline.module.css"));
const formatDate = (ts) => {
if (date_fns_1.isToday(ts)) {
return date_fns_1.format(ts, 'HH:mm:ss');
}
return date_fns_1.getYear(ts) === date_fns_1.getYear(new Date())
? date_fns_1.format(ts, 'MM/dd HH:mm:ss')
: date_fns_1.format(ts, 'MM/dd/yyyy HH:mm:ss');
};
const Timeline = function Timeline({ job, status, }) {
return (react_1.default.createElement("div", { className: Timeline_module_css_1.default.timelineWrapper },
react_1.default.createElement("ul", { className: Timeline_module_css_1.default.timeline },
react_1.default.createElement("li", null,
react_1.default.createElement("small", null, "Added at"),
react_1.default.createElement("time", null, formatDate(job.timestamp || 0))),
!!job.delay && job.delay > 0 && status === 'delayed' && (react_1.default.createElement("li", null,
react_1.default.createElement("small", null, "Delayed for"),
react_1.default.createElement("time", null, date_fns_1.formatDistance(job.timestamp || 0, (job.timestamp || 0) + job.delay, { includeSeconds: true })))),
!!job.processedOn && (react_1.default.createElement("li", null,
react_1.default.createElement("small", null,
job.delay && job.delay > 0 ? 'delayed for ' : '',
date_fns_1.formatDistance(job.processedOn, job.timestamp || 0, {
includeSeconds: true,
})),
react_1.default.createElement("small", null, "Process started at"),
react_1.default.createElement("time", null, formatDate(job.processedOn)))),
!!job.finishedOn && (react_1.default.createElement("li", null,
react_1.default.createElement("small", null, date_fns_1.formatDistance(job.finishedOn, job.processedOn || 0, {
includeSeconds: true,
})),
react_1.default.createElement("small", null,
status === 'failed' ? 'Failed' : 'Finished',
" at"),
react_1.default.createElement("time", null, formatDate(job.finishedOn)))))));
};
exports.Timeline = Timeline;
//# sourceMappingURL=Timeline.js.map
@@ -0,0 +1 @@
{"version":3,"file":"Timeline.js","sourceRoot":"","sources":["../../../../../src/ui/components/JobCard/Timeline/Timeline.tsx"],"names":[],"mappings":";;;;;;AAAA,uCAAmE;AACnE,kDAAyB;AAGzB,gFAAqC;AAIrC,MAAM,UAAU,GAAG,CAAC,EAAa,EAAE,EAAE;IACnC,IAAI,kBAAO,CAAC,EAAE,CAAC,EAAE;QACf,OAAO,iBAAM,CAAC,EAAE,EAAE,UAAU,CAAC,CAAA;KAC9B;IAED,OAAO,kBAAO,CAAC,EAAE,CAAC,KAAK,kBAAO,CAAC,IAAI,IAAI,EAAE,CAAC;QACxC,CAAC,CAAC,iBAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC;QAC9B,CAAC,CAAC,iBAAM,CAAC,EAAE,EAAE,qBAAqB,CAAC,CAAA;AACvC,CAAC,CAAA;AAEM,MAAM,QAAQ,GAAG,SAAS,QAAQ,CAAC,EACxC,GAAG,EACH,MAAM,GAIP;IACC,OAAO,CACL,uCAAK,SAAS,EAAE,6BAAC,CAAC,eAAe;QAC/B,sCAAI,SAAS,EAAE,6BAAC,CAAC,QAAQ;YACvB;gBACE,wDAAuB;gBACvB,4CAAO,UAAU,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,CAAC,CAAQ,CAC1C;YACJ,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,MAAM,KAAK,SAAS,IAAI,CACvD;gBACE,2DAA0B;gBAC1B,4CACG,yBAAc,CACb,GAAG,CAAC,SAAS,IAAI,CAAC,EAClB,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,EAChC,EAAE,cAAc,EAAE,IAAI,EAAE,CACzB,CACI,CACJ,CACN;YACA,CAAC,CAAC,GAAG,CAAC,WAAW,IAAI,CACpB;gBACE;oBACG,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE;oBAChD,yBAAc,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,SAAS,IAAI,CAAC,EAAE;wBACnD,cAAc,EAAE,IAAI;qBACrB,CAAC,CACI;gBACR,kEAAiC;gBACjC,4CAAO,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,CAAQ,CACvC,CACN;YACA,CAAC,CAAC,GAAG,CAAC,UAAU,IAAI,CACnB;gBACE,6CACG,yBAAc,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,WAAW,IAAI,CAAC,EAAE;oBACpD,cAAc,EAAE,IAAI;iBACrB,CAAC,CACI;gBACR;oBAAQ,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU;0BAAY;gBAC/D,4CAAO,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAQ,CACtC,CACN,CACE,CACD,CACP,CAAA;AACH,CAAC,CAAA;AApDY,QAAA,QAAQ,YAoDpB"}
+6
View File
@@ -0,0 +1,6 @@
/// <reference types="react" />
import { Store } from '../../hooks/useStore';
export declare const Menu: ({ queues, selectedStatuses, }: {
queues: string[] | undefined;
selectedStatuses: Store['selectedStatuses'];
}) => JSX.Element;
+20
View File
@@ -0,0 +1,20 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Menu = void 0;
const react_1 = __importDefault(require("react"));
const react_router_dom_1 = require("react-router-dom");
const constants_1 = require("../constants");
const Menu_module_css_1 = __importDefault(require("./Menu.module.css"));
const Menu = ({ queues, selectedStatuses, }) => (react_1.default.createElement("aside", { className: Menu_module_css_1.default.aside },
react_1.default.createElement("div", null, "QUEUES"),
react_1.default.createElement("nav", null, !!queues && (react_1.default.createElement("ul", { className: Menu_module_css_1.default.menu }, queues.map((queueName) => (react_1.default.createElement("li", { key: queueName },
react_1.default.createElement(react_router_dom_1.NavLink, { to: `/queue/${encodeURIComponent(queueName)}${!selectedStatuses[queueName] ||
selectedStatuses[queueName] === constants_1.STATUS_LIST[0]
? ''
: `?status=${selectedStatuses[queueName]}`}`, activeClassName: Menu_module_css_1.default.active, title: queueName }, queueName))))))),
react_1.default.createElement("div", { className: Menu_module_css_1.default.appVersion }, process.env.APP_VERSION)));
exports.Menu = Menu;
//# sourceMappingURL=Menu.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"Menu.js","sourceRoot":"","sources":["../../../../src/ui/components/Menu/Menu.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AACzB,uDAA0C;AAE1C,4CAA0C;AAC1C,wEAAiC;AAE1B,MAAM,IAAI,GAAG,CAAC,EACnB,MAAM,EACN,gBAAgB,GAIjB,EAAE,EAAE,CAAC,CACJ,yCAAO,SAAS,EAAE,yBAAC,CAAC,KAAK;IACvB,oDAAiB;IACjB,2CACG,CAAC,CAAC,MAAM,IAAI,CACX,sCAAI,SAAS,EAAE,yBAAC,CAAC,IAAI,IAClB,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CACzB,sCAAI,GAAG,EAAE,SAAS;QAChB,8BAAC,0BAAO,IACN,EAAE,EAAE,UAAU,kBAAkB,CAAC,SAAS,CAAC,GACzC,CAAC,gBAAgB,CAAC,SAAS,CAAC;gBAC5B,gBAAgB,CAAC,SAAS,CAAC,KAAK,uBAAW,CAAC,CAAC,CAAC;gBAC5C,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,WAAW,gBAAgB,CAAC,SAAS,CAAC,EAC5C,EAAE,EACF,eAAe,EAAE,yBAAC,CAAC,MAAM,EACzB,KAAK,EAAE,SAAS,IAEf,SAAS,CACF,CACP,CACN,CAAC,CACC,CACN,CACG;IACN,uCAAK,SAAS,EAAE,yBAAC,CAAC,UAAU,IAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAO,CACvD,CACT,CAAA;AAjCY,QAAA,IAAI,QAiChB"}
@@ -0,0 +1,11 @@
/// <reference types="react" />
import { AppQueue } from '../../../@types/app';
import { Store } from '../../hooks/useStore';
import { Status } from '../constants';
interface QueueActionProps {
queue: AppQueue;
actions: Store['actions'];
status: Status;
}
export declare const QueueActions: ({ status, actions, queue }: QueueActionProps) => JSX.Element | null;
export {};
@@ -0,0 +1,35 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.QueueActions = void 0;
const react_1 = __importDefault(require("react"));
const Retry_1 = require("../Icons/Retry");
const Trash_1 = require("../Icons/Trash");
const Button_1 = require("../JobCard/Button/Button");
const QueueActions_module_css_1 = __importDefault(require("./QueueActions.module.css"));
const ACTIONABLE_STATUSES = ['failed', 'delayed', 'completed'];
const isStatusActionable = (status) => ACTIONABLE_STATUSES.includes(status);
const CleanAllButton = ({ onClick }) => (react_1.default.createElement(Button_1.Button, { onClick: onClick, className: QueueActions_module_css_1.default.button },
react_1.default.createElement(Trash_1.TrashIcon, null),
"Clean all"));
const QueueActions = ({ status, actions, queue }) => {
if (!isStatusActionable(status)) {
return null;
}
return (react_1.default.createElement("ul", { className: QueueActions_module_css_1.default.queueActions },
status === 'failed' && (react_1.default.createElement(react_1.default.Fragment, null,
react_1.default.createElement("li", null,
react_1.default.createElement(Button_1.Button, { onClick: actions.retryAll(queue.name), className: QueueActions_module_css_1.default.button },
react_1.default.createElement(Retry_1.RetryIcon, null),
"Retry all")),
react_1.default.createElement("li", null,
react_1.default.createElement(CleanAllButton, { onClick: actions.cleanAllFailed(queue.name) })))),
status === 'delayed' && (react_1.default.createElement("li", null,
react_1.default.createElement(CleanAllButton, { onClick: actions.cleanAllDelayed(queue.name) }))),
status === 'completed' && (react_1.default.createElement("li", null,
react_1.default.createElement(CleanAllButton, { onClick: actions.cleanAllCompleted(queue.name) })))));
};
exports.QueueActions = QueueActions;
//# sourceMappingURL=QueueActions.js.map
@@ -0,0 +1 @@
{"version":3,"file":"QueueActions.js","sourceRoot":"","sources":["../../../../src/ui/components/QueueActions/QueueActions.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AAIzB,0CAA0C;AAC1C,0CAA0C;AAC1C,qDAAiD;AACjD,wFAAyC;AAQzC,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,WAAW,CAAC,CAAA;AAE9D,MAAM,kBAAkB,GAAG,CAAC,MAAc,EAAW,EAAE,CACrD,mBAAmB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;AAEtC,MAAM,cAAc,GAAG,CAAC,EAAE,OAAO,EAAO,EAAE,EAAE,CAAC,CAC3C,8BAAC,eAAM,IAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,iCAAC,CAAC,MAAM;IAC3C,8BAAC,iBAAS,OAAG;gBAEN,CACV,CAAA;AAEM,MAAM,YAAY,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAoB,EAAE,EAAE;IAC3E,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE;QAC/B,OAAO,IAAI,CAAA;KACZ;IAED,OAAO,CACL,sCAAI,SAAS,EAAE,iCAAC,CAAC,YAAY;QAC1B,MAAM,KAAK,QAAQ,IAAI,CACtB;YACE;gBACE,8BAAC,eAAM,IAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,iCAAC,CAAC,MAAM;oBAChE,8BAAC,iBAAS,OAAG;gCAEN,CACN;YACL;gBACE,8BAAC,cAAc,IAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,GAAI,CAC5D,CACJ,CACJ;QACA,MAAM,KAAK,SAAS,IAAI,CACvB;YACE,8BAAC,cAAc,IAAC,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,GAAI,CAC7D,CACN;QACA,MAAM,KAAK,WAAW,IAAI,CACzB;YACE,8BAAC,cAAc,IAAC,OAAO,EAAE,OAAO,CAAC,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,GAAI,CAC/D,CACN,CACE,CACN,CAAA;AACH,CAAC,CAAA;AAhCY,QAAA,YAAY,gBAgCxB"}
@@ -0,0 +1,8 @@
/// <reference types="react" />
import { AppQueue } from '../../../@types/app';
import { Store } from '../../hooks/useStore';
export declare const QueuePage: ({ selectedStatus, actions, queue, }: {
queue: AppQueue | undefined;
actions: Store['actions'];
selectedStatus: Store['selectedStatuses'];
}) => JSX.Element;
@@ -0,0 +1,28 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.QueuePage = void 0;
const react_1 = __importDefault(require("react"));
const JobCard_1 = require("../JobCard/JobCard");
const QueueActions_1 = require("../QueueActions/QueueActions");
const StatusMenu_1 = require("../StatusMenu/StatusMenu");
const QueuePage_module_css_1 = __importDefault(require("./QueuePage.module.css"));
const QueuePage = ({ selectedStatus, actions, queue, }) => {
if (!queue) {
return react_1.default.createElement("section", null, "Queue Not found");
}
return (react_1.default.createElement("section", null,
react_1.default.createElement("div", { className: QueuePage_module_css_1.default.stickyHeader },
react_1.default.createElement(StatusMenu_1.StatusMenu, { queue: queue }),
!queue.readOnlyMode && (react_1.default.createElement(QueueActions_1.QueueActions, { queue: queue, actions: actions, status: selectedStatus[queue.name] }))),
queue.jobs.map((job) => (react_1.default.createElement(JobCard_1.JobCard, { key: job.id, job: job, status: selectedStatus[queue.name], actions: {
cleanJob: actions.cleanJob(queue === null || queue === void 0 ? void 0 : queue.name)(job),
promoteJob: actions.promoteJob(queue === null || queue === void 0 ? void 0 : queue.name)(job),
retryJob: actions.retryJob(queue === null || queue === void 0 ? void 0 : queue.name)(job),
getJobLogs: actions.getJobLogs(queue === null || queue === void 0 ? void 0 : queue.name)(job),
}, readOnlyMode: queue === null || queue === void 0 ? void 0 : queue.readOnlyMode })))));
};
exports.QueuePage = QueuePage;
//# sourceMappingURL=QueuePage.js.map
@@ -0,0 +1 @@
{"version":3,"file":"QueuePage.js","sourceRoot":"","sources":["../../../../src/ui/components/QueuePage/QueuePage.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AAGzB,gDAA4C;AAC5C,+DAA2D;AAC3D,yDAAqD;AACrD,kFAAsC;AAE/B,MAAM,SAAS,GAAG,CAAC,EACxB,cAAc,EACd,OAAO,EACP,KAAK,GAKN,EAAE,EAAE;IACH,IAAI,CAAC,KAAK,EAAE;QACV,OAAO,iEAAkC,CAAA;KAC1C;IAED,OAAO,CACL;QACE,uCAAK,SAAS,EAAE,8BAAC,CAAC,YAAY;YAC5B,8BAAC,uBAAU,IAAC,KAAK,EAAE,KAAK,GAAI;YAC3B,CAAC,KAAK,CAAC,YAAY,IAAI,CACtB,8BAAC,2BAAY,IACX,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,GAClC,CACH,CACG;QACL,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACvB,8BAAC,iBAAO,IACN,GAAG,EAAE,GAAG,CAAC,EAAE,EACX,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,EAClC,OAAO,EAAE;gBACP,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,IAAI,CAAC,CAAC,GAAG,CAAC;gBAC5C,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,IAAI,CAAC,CAAC,GAAG,CAAC;gBAChD,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,IAAI,CAAC,CAAC,GAAG,CAAC;gBAC5C,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,IAAI,CAAC,CAAC,GAAG,CAAC;aACjD,EACD,YAAY,EAAE,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,YAAY,GACjC,CACH,CAAC,CACM,CACX,CAAA;AACH,CAAC,CAAA;AAzCY,QAAA,SAAS,aAyCrB"}
@@ -0,0 +1,5 @@
/// <reference types="react" />
import { ValidMetrics } from '../../../@types/app';
export declare const RedisStats: ({ stats }: {
stats: Partial<ValidMetrics>;
}) => JSX.Element;
@@ -0,0 +1,52 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RedisStats = void 0;
const pretty_bytes_1 = __importDefault(require("pretty-bytes"));
const react_1 = __importDefault(require("react"));
const RedisStats_module_css_1 = __importDefault(require("./RedisStats.module.css"));
const RedisLogo = () => (react_1.default.createElement("svg", { width: 42, role: "img", viewBox: "0 0 24 24" },
react_1.default.createElement("path", { fill: "#CBD5E0", d: "M23.99314 6.28305c.012-.244-.307-.458-.949-.694-1.248-.457-7.843-3.082-9.106-3.545-1.263-.462-1.777-.443-3.261.089-1.484.533-8.506 3.287-9.755 3.776-.625.246-.931.473-.92.715v2.426c0 .242.334.498.97.802 1.272.608 8.332 3.461 9.448 3.994 1.116.533 1.9.54 3.313-.196 1.412-.736 8.047-3.465 9.328-4.132.651-.34.939-.604.939-.843 0-.225.001-2.392.001-2.392h-.008zm-15.399 2.296l5.561-.854-1.68 2.463-3.881-1.609zm12.299-2.218l-3.288 1.299-.357.14-3.287-1.299 3.642-1.44 3.29 1.3zm-9.655-2.383l-.538-.992 1.678.656 1.582-.518-.428 1.025 1.612.604-2.079.216-.466 1.12-.752-1.249-2.401-.216 1.792-.646zm-4.143 1.399c1.642 0 2.972.516 2.972 1.152 0 .636-1.331 1.152-2.972 1.152s-2.973-.517-2.973-1.152c0-.636 1.331-1.152 2.973-1.152z" }),
react_1.default.createElement("path", { fill: "#E2E8F0", d: "M23.99314 10.38505c-.011.229-.313.484-.934.809-1.281.667-7.916 3.396-9.328 4.132-1.413.736-2.197.729-3.313.196-1.116-.533-8.176-3.386-9.448-3.994-.635-.303-.959-.56-.97-.801v2.426c0 .242.334.498.97.802 1.272.608 8.332 3.46 9.448 3.993 1.116.534 1.9.541 3.313-.195 1.412-.736 8.047-3.465 9.328-4.132.651-.34.939-.604.939-.843 0-.226.001-2.392.001-2.392-.001-.001-.004 0-.006-.001z" }),
react_1.default.createElement("path", { fill: "#EDF2F7", d: "M23.99414 14.34005c-.01.229-.313.485-.935.81-1.281.667-7.916 3.396-9.328 4.132-1.413.736-2.197.729-3.313.195-1.116-.533-8.176-3.386-9.448-3.993-.635-.304-.959-.56-.97-.802v2.426c0 .242.334.499.97.803 1.272.608 8.333 3.46 9.448 3.993 1.116.534 1.9.541 3.313-.196 1.412-.736 8.047-3.464 9.328-4.132.651-.339.939-.603.939-.842 0-.226.001-2.392.001-2.392-.001-.001-.004-.001-.005-.002z" })));
const getMemoryUsage = (used_memory, total_system_memory) => {
if (used_memory === undefined) {
return '-';
}
const usedMemory = parseInt(used_memory, 10);
if (total_system_memory === undefined) {
return pretty_bytes_1.default(usedMemory);
}
const totalSystemMemory = parseInt(total_system_memory, 10);
return `${((usedMemory / totalSystemMemory) * 100).toFixed(2)}%`;
};
const RedisStats = ({ stats }) => {
const { redis_version, used_memory, total_system_memory, mem_fragmentation_ratio, connected_clients, blocked_clients, } = stats;
return (react_1.default.createElement("div", { className: RedisStats_module_css_1.default.stats },
react_1.default.createElement("div", null,
react_1.default.createElement(RedisLogo, null)),
react_1.default.createElement("div", null,
"Version",
react_1.default.createElement("span", null, redis_version)),
react_1.default.createElement("div", null,
"Memory usage",
react_1.default.createElement("span", null, getMemoryUsage(used_memory, total_system_memory)),
total_system_memory && used_memory ? (react_1.default.createElement("small", null,
pretty_bytes_1.default(parseInt(used_memory)),
" of",
' ',
pretty_bytes_1.default(parseInt(total_system_memory)))) : (react_1.default.createElement("small", { className: "error" }, "Could not retrieve memory stats"))),
react_1.default.createElement("div", null,
"Fragmentation ratio",
react_1.default.createElement("span", null, mem_fragmentation_ratio)),
react_1.default.createElement("div", null,
"Connected clients",
react_1.default.createElement("span", null, connected_clients)),
react_1.default.createElement("div", null,
"Blocked clients",
react_1.default.createElement("span", null, blocked_clients))));
};
exports.RedisStats = RedisStats;
//# sourceMappingURL=RedisStats.js.map
@@ -0,0 +1 @@
{"version":3,"file":"RedisStats.js","sourceRoot":"","sources":["../../../../src/ui/components/RedisStats/RedisStats.tsx"],"names":[],"mappings":";;;;;;AAAA,gEAAsC;AACtC,kDAAyB;AAEzB,oFAAuC;AAEvC,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,CACtB,uCAAK,KAAK,EAAE,EAAE,EAAE,IAAI,EAAC,KAAK,EAAC,OAAO,EAAC,WAAW;IAC5C,wCACE,IAAI,EAAC,SAAS,EACd,CAAC,EAAC,utBAAutB,GACztB;IACF,wCACE,IAAI,EAAC,SAAS,EACd,CAAC,EAAC,6XAA6X,GAC/X;IACF,wCACE,IAAI,EAAC,SAAS,EACd,CAAC,EAAC,+XAA+X,GACjY,CACE,CACP,CAAA;AAED,MAAM,cAAc,GAAG,CACrB,WAAyC,EACzC,mBAAyD,EACzD,EAAE;IACF,IAAI,WAAW,KAAK,SAAS,EAAE;QAC7B,OAAO,GAAG,CAAA;KACX;IACD,MAAM,UAAU,GAAG,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;IAE5C,IAAI,mBAAmB,KAAK,SAAS,EAAE;QACrC,OAAO,sBAAW,CAAC,UAAU,CAAC,CAAA;KAC/B;IACD,MAAM,iBAAiB,GAAG,QAAQ,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAA;IAE3D,OAAO,GAAG,CAAC,CAAC,UAAU,GAAG,iBAAiB,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAA;AAClE,CAAC,CAAA;AAEM,MAAM,UAAU,GAAG,CAAC,EAAE,KAAK,EAAoC,EAAE,EAAE;IACxE,MAAM,EACJ,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,uBAAuB,EACvB,iBAAiB,EACjB,eAAe,GAChB,GAAG,KAAK,CAAA;IAET,OAAO,CACL,uCAAK,SAAS,EAAE,+BAAC,CAAC,KAAK;QACrB;YACE,8BAAC,SAAS,OAAG,CACT;QAEN;;YAEE,4CAAO,aAAa,CAAQ,CACxB;QAEN;;YAEE,4CAAO,cAAc,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAQ;YAC9D,mBAAmB,IAAI,WAAW,CAAC,CAAC,CAAC,CACpC;gBACG,sBAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;;gBAAK,GAAG;gBAC1C,sBAAW,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CACrC,CACT,CAAC,CAAC,CAAC,CACF,yCAAO,SAAS,EAAC,OAAO,sCAAwC,CACjE,CACG;QAEN;;YAEE,4CAAO,uBAAuB,CAAQ,CAClC;QAEN;;YAEE,4CAAO,iBAAiB,CAAQ,CAC5B;QAEN;;YAEE,4CAAO,eAAe,CAAQ,CAC1B,CACF,CACP,CAAA;AACH,CAAC,CAAA;AAlDY,QAAA,UAAU,cAkDtB"}
@@ -0,0 +1,5 @@
/// <reference types="react" />
import { AppQueue } from '../../../@types/app';
export declare const StatusMenu: ({ queue }: {
queue: AppQueue;
}) => JSX.Element;
@@ -0,0 +1,26 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.StatusMenu = void 0;
const react_1 = __importDefault(require("react"));
const react_router_dom_1 = require("react-router-dom");
const constants_1 = require("../constants");
const StatusMenu_module_css_1 = __importDefault(require("./StatusMenu.module.css"));
const StatusMenu = ({ queue }) => {
const { url } = react_router_dom_1.useRouteMatch();
return (react_1.default.createElement("div", { className: StatusMenu_module_css_1.default.statusMenu }, constants_1.STATUS_LIST.map((status) => {
const isLatest = status === constants_1.STATUSES.latest;
const displayStatus = status.toLocaleUpperCase();
return (react_1.default.createElement(react_router_dom_1.NavLink, { to: `${url}${isLatest ? '' : `?status=${status}`}`, activeClassName: StatusMenu_module_css_1.default.active, isActive: (_path, { search }) => {
const query = new URLSearchParams(search);
return (query.get('status') === status ||
(isLatest && query.get('status') === null));
}, key: `${queue.name}-${status}` },
react_1.default.createElement("span", { title: displayStatus }, displayStatus),
queue.counts[status] > 0 && (react_1.default.createElement("span", { className: StatusMenu_module_css_1.default.badge }, queue.counts[status]))));
})));
};
exports.StatusMenu = StatusMenu;
//# sourceMappingURL=StatusMenu.js.map
@@ -0,0 +1 @@
{"version":3,"file":"StatusMenu.js","sourceRoot":"","sources":["../../../../src/ui/components/StatusMenu/StatusMenu.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AACzB,uDAAyD;AAEzD,4CAAoD;AACpD,oFAAuC;AAEhC,MAAM,UAAU,GAAG,CAAC,EAAE,KAAK,EAAuB,EAAE,EAAE;IAC3D,MAAM,EAAE,GAAG,EAAE,GAAG,gCAAa,EAAE,CAAA;IAE/B,OAAO,CACL,uCAAK,SAAS,EAAE,+BAAC,CAAC,UAAU,IACzB,uBAAW,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QAC1B,MAAM,QAAQ,GAAG,MAAM,KAAK,oBAAQ,CAAC,MAAM,CAAA;QAC3C,MAAM,aAAa,GAAG,MAAM,CAAC,iBAAiB,EAAE,CAAA;QAChD,OAAO,CACL,8BAAC,0BAAO,IACN,EAAE,EAAE,GAAG,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,MAAM,EAAE,EAAE,EAClD,eAAe,EAAE,+BAAC,CAAC,MAAM,EACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;gBAC9B,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,CAAA;gBACzC,OAAO,CACL,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,MAAM;oBAC9B,CAAC,QAAQ,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,CAC3C,CAAA;YACH,CAAC,EACD,GAAG,EAAE,GAAG,KAAK,CAAC,IAAI,IAAI,MAAM,EAAE;YAE9B,wCAAM,KAAK,EAAE,aAAa,IAAG,aAAa,CAAQ;YACjD,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAC3B,wCAAM,SAAS,EAAE,+BAAC,CAAC,KAAK,IAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAQ,CACxD,CACO,CACX,CAAA;IACH,CAAC,CAAC,CACE,CACP,CAAA;AACH,CAAC,CAAA;AA9BY,QAAA,UAAU,cA8BtB"}
@@ -0,0 +1,4 @@
import React from 'react';
export declare const Tooltip: ({ title, children, }: React.PropsWithChildren<{
title: string;
}>) => JSX.Element;
+11
View File
@@ -0,0 +1,11 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Tooltip = void 0;
const react_1 = __importDefault(require("react"));
const Tooltip_module_css_1 = __importDefault(require("./Tooltip.module.css"));
const Tooltip = ({ title, children, }) => (react_1.default.createElement("span", { "data-title": title, className: Tooltip_module_css_1.default.tooltip }, children));
exports.Tooltip = Tooltip;
//# sourceMappingURL=Tooltip.js.map
@@ -0,0 +1 @@
{"version":3,"file":"Tooltip.js","sourceRoot":"","sources":["../../../../src/ui/components/Tooltip/Tooltip.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AACzB,8EAAoC;AAE7B,MAAM,OAAO,GAAG,CAAC,EACtB,KAAK,EACL,QAAQ,GACmC,EAAE,EAAE,CAAC,CAChD,sDAAkB,KAAK,EAAE,SAAS,EAAE,4BAAC,CAAC,OAAO,IAC1C,QAAQ,CACJ,CACR,CAAA;AAPY,QAAA,OAAO,WAOnB"}
+14
View File
@@ -0,0 +1,14 @@
import { KeyOf } from '../../@types/utils';
export declare const STATUSES: {
latest: string;
active: string;
waiting: string;
completed: string;
failed: string;
delayed: string;
paused: string;
};
export declare const STATUS_LIST: KeyOf<typeof STATUSES>;
export declare type Status = keyof typeof STATUSES;
export declare type Field = 'attempts' | 'data' | 'id' | 'name' | 'opts' | 'progress' | 'timestamps' | 'delay' | 'failedReason' | 'retry' | 'promote' | 'clean';
export declare const FIELDS: Record<Status, Field[]>;
+60
View File
@@ -0,0 +1,60 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FIELDS = exports.STATUS_LIST = exports.STATUSES = void 0;
exports.STATUSES = {
latest: 'latest',
active: 'active',
waiting: 'waiting',
completed: 'completed',
failed: 'failed',
delayed: 'delayed',
paused: 'paused',
};
exports.STATUS_LIST = [
exports.STATUSES.latest,
exports.STATUSES.active,
exports.STATUSES.waiting,
exports.STATUSES.completed,
exports.STATUSES.failed,
exports.STATUSES.delayed,
exports.STATUSES.paused,
];
exports.FIELDS = {
active: ['attempts', 'data', 'id', 'name', 'opts', 'progress', 'timestamps'],
completed: [
'attempts',
'data',
'id',
'name',
'opts',
'progress',
'timestamps',
],
delayed: [
'attempts',
'data',
'delay',
'id',
'name',
'opts',
'promote',
'timestamps',
'clean',
],
failed: [
'attempts',
'failedReason',
'data',
'opts',
'id',
'name',
'progress',
'retry',
'timestamps',
'clean',
],
latest: ['attempts', 'data', 'id', 'name', 'opts', 'progress', 'timestamps'],
paused: ['attempts', 'data', 'id', 'name', 'opts', 'timestamps'],
waiting: ['data', 'id', 'name', 'opts', 'timestamps', 'clean'],
};
//# sourceMappingURL=constants.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/ui/components/constants.ts"],"names":[],"mappings":";;;AAEa,QAAA,QAAQ,GAAG;IACtB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,WAAW;IACtB,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;CACjB,CAAA;AAEY,QAAA,WAAW,GAA2B;IACjD,gBAAQ,CAAC,MAAa;IACtB,gBAAQ,CAAC,MAAM;IACf,gBAAQ,CAAC,OAAO;IAChB,gBAAQ,CAAC,SAAS;IAClB,gBAAQ,CAAC,MAAM;IACf,gBAAQ,CAAC,OAAO;IAChB,gBAAQ,CAAC,MAAM;CAChB,CAAA;AAkBY,QAAA,MAAM,GAA4B;IAC7C,MAAM,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,CAAC;IAC5E,SAAS,EAAE;QACT,UAAU;QACV,MAAM;QACN,IAAI;QACJ,MAAM;QACN,MAAM;QACN,UAAU;QACV,YAAY;KACb;IACD,OAAO,EAAE;QACP,UAAU;QACV,MAAM;QACN,OAAO;QACP,IAAI;QACJ,MAAM;QACN,MAAM;QACN,SAAS;QACT,YAAY;QACZ,OAAO;KACR;IACD,MAAM,EAAE;QACN,UAAU;QACV,cAAc;QACd,MAAM;QACN,MAAM;QACN,IAAI;QACJ,MAAM;QACN,UAAU;QACV,OAAO;QACP,YAAY;QACZ,OAAO;KACR;IACD,MAAM,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,CAAC;IAC5E,MAAM,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC;IAChE,OAAO,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC;CAC/D,CAAA"}
+12
View File
@@ -0,0 +1,12 @@
import { Status } from '../components/constants';
declare const regularItems: readonly ["Data", "Options", "Logs"];
export declare type TabsType = typeof regularItems[number] | 'Error';
export declare function useDetailsTabs(currentStatus: Status): {
tabs: {
title: TabsType;
isActive: boolean;
selectTab: () => void;
}[];
selectedTab: TabsType;
};
export {};
+26
View File
@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useDetailsTabs = void 0;
const react_1 = require("react");
const constants_1 = require("../components/constants");
const regularItems = ['Data', 'Options', 'Logs'];
function useDetailsTabs(currentStatus) {
const [tabs, updateTabs] = react_1.useState([]);
const [selectedTabIdx, setSelectedTabIdx] = react_1.useState(0);
const selectedTab = tabs[selectedTabIdx];
react_1.useEffect(() => {
updateTabs(currentStatus === constants_1.STATUSES.failed
? ['Error', ...regularItems]
: [...regularItems]);
}, [currentStatus]);
return {
tabs: tabs.map((title, index) => ({
title,
isActive: title === selectedTab,
selectTab: () => setSelectedTabIdx(index),
})),
selectedTab,
};
}
exports.useDetailsTabs = useDetailsTabs;
//# sourceMappingURL=useDetailsTabs.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"useDetailsTabs.js","sourceRoot":"","sources":["../../../src/ui/hooks/useDetailsTabs.tsx"],"names":[],"mappings":";;;AAAA,iCAA2C;AAC3C,uDAA0D;AAE1D,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAU,CAAA;AAIzD,SAAgB,cAAc,CAAC,aAAqB;IAClD,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,GAAG,gBAAQ,CAAa,EAAE,CAAC,CAAA;IACnD,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,gBAAQ,CAAC,CAAC,CAAC,CAAA;IACvD,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,CAAA;IAExC,iBAAS,CAAC,GAAG,EAAE;QACb,UAAU,CACR,aAAa,KAAK,oBAAQ,CAAC,MAAM;YAC/B,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,YAAY,CAAC;YAC5B,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CACtB,CAAA;IACH,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAA;IAEnB,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;YAChC,KAAK;YACL,QAAQ,EAAE,KAAK,KAAK,WAAW;YAC/B,SAAS,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC;SAC1C,CAAC,CAAC;QACH,WAAW;KACZ,CAAA;AACH,CAAC;AArBD,wCAqBC"}
+1
View File
@@ -0,0 +1 @@
export declare function useInterval(callback: () => void, delay: number | null, deps?: any[]): void;
+25
View File
@@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useInterval = void 0;
const react_1 = require("react");
function useInterval(callback, delay, deps = []) {
const savedCallback = react_1.useRef(callback);
// Remember the latest callback if it changes.
react_1.useEffect(() => {
savedCallback.current = callback;
}, [callback]);
// Set up the interval.
react_1.useEffect(() => {
// Don't schedule if no delay is specified.
if (delay === null) {
return;
}
savedCallback.current();
const id = setInterval(() => savedCallback.current(), delay);
return () => {
clearInterval(id);
};
}, [delay, ...deps]);
}
exports.useInterval = useInterval;
//# sourceMappingURL=useInterval.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"useInterval.js","sourceRoot":"","sources":["../../../src/ui/hooks/useInterval.ts"],"names":[],"mappings":";;;AAAA,iCAAyC;AAEzC,SAAgB,WAAW,CACzB,QAAoB,EACpB,KAAoB,EACpB,OAAc,EAAE;IAEhB,MAAM,aAAa,GAAG,cAAM,CAAC,QAAQ,CAAC,CAAA;IAEtC,8CAA8C;IAC9C,iBAAS,CAAC,GAAG,EAAE;QACb,aAAa,CAAC,OAAO,GAAG,QAAQ,CAAA;IAClC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,uBAAuB;IACvB,iBAAS,CAAC,GAAG,EAAE;QACb,2CAA2C;QAC3C,IAAI,KAAK,KAAK,IAAI,EAAE;YAClB,OAAM;SACP;QAED,aAAa,CAAC,OAAO,EAAE,CAAA;QAEvB,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,CAAA;QAE5D,OAAO,GAAG,EAAE;YACV,aAAa,CAAC,EAAE,CAAC,CAAA;QACnB,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC,CAAA;AACtB,CAAC;AA3BD,kCA2BC"}
+1
View File
@@ -0,0 +1 @@
export declare function useScrollTopOnNav(): void;
+13
View File
@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useScrollTopOnNav = void 0;
const react_1 = require("react");
const react_router_dom_1 = require("react-router-dom");
function useScrollTopOnNav() {
const { key } = react_router_dom_1.useLocation();
react_1.useEffect(() => {
window.scrollTo(0, 0);
}, [key]);
}
exports.useScrollTopOnNav = useScrollTopOnNav;
//# sourceMappingURL=useScrollTopOnNav.js.map
@@ -0,0 +1 @@
{"version":3,"file":"useScrollTopOnNav.js","sourceRoot":"","sources":["../../../src/ui/hooks/useScrollTopOnNav.ts"],"names":[],"mappings":";;;AAAA,iCAAiC;AACjC,uDAA8C;AAE9C,SAAgB,iBAAiB;IAC/B,MAAM,EAAE,GAAG,EAAE,GAAG,8BAAW,EAAE,CAAA;IAC7B,iBAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACvB,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;AACX,CAAC;AALD,8CAKC"}
@@ -0,0 +1,2 @@
import { SelectedStatuses } from '../../@types/app';
export declare function useSelectedStatuses(): SelectedStatuses;
+22
View File
@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useSelectedStatuses = void 0;
const react_1 = require("react");
const react_router_dom_1 = require("react-router-dom");
const constants_1 = require("../components/constants");
function useSelectedStatuses() {
const { search, pathname } = react_router_dom_1.useLocation();
const match = react_router_dom_1.useRouteMatch({ path: '/queue/:name' });
const [selectedStatuses, setSelectedStatuses] = react_1.useState({});
react_1.useEffect(() => {
const query = new URLSearchParams(search);
const status = query.get('status') || constants_1.STATUS_LIST[0];
const queue = match ? decodeURIComponent(match === null || match === void 0 ? void 0 : match.params.name) : '';
if (queue) {
setSelectedStatuses({ ...selectedStatuses, [queue]: status });
}
}, [search, pathname]);
return selectedStatuses;
}
exports.useSelectedStatuses = useSelectedStatuses;
//# sourceMappingURL=useSelectedStatuses.js.map
@@ -0,0 +1 @@
{"version":3,"file":"useSelectedStatuses.js","sourceRoot":"","sources":["../../../src/ui/hooks/useSelectedStatuses.ts"],"names":[],"mappings":";;;AAAA,iCAA2C;AAC3C,uDAA6D;AAE7D,uDAA6D;AAE7D,SAAgB,mBAAmB;IACjC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,8BAAW,EAAE,CAAA;IAC1C,MAAM,KAAK,GAAG,gCAAa,CAAmB,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAA;IAEvE,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,gBAAQ,CAAmB,EAAE,CAAC,CAAA;IAE9E,iBAAS,CAAC,GAAG,EAAE;QACb,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,CAAA;QACzC,MAAM,MAAM,GAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAY,IAAI,uBAAW,CAAC,CAAC,CAAC,CAAA;QAChE,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,kBAAkB,CAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QACjE,IAAI,KAAK,EAAE;YACT,mBAAmB,CAAC,EAAE,GAAG,gBAAgB,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;SAC9D;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAA;IAEtB,OAAO,gBAAgB,CAAA;AACzB,CAAC;AAhBD,kDAgBC"}
+14
View File
@@ -0,0 +1,14 @@
import * as api from '../../@types/api';
import { QueueActions, SelectedStatuses } from '../../@types/app';
import { Api } from '../services/Api';
declare type State = {
data: null | api.GetQueues;
loading: boolean;
};
export interface Store {
state: State;
actions: QueueActions;
selectedStatuses: SelectedStatuses;
}
export declare const useStore: (api: Api) => Store;
export {};
+46
View File
@@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useStore = void 0;
const react_1 = require("react");
const useInterval_1 = require("./useInterval");
const useSelectedStatuses_1 = require("./useSelectedStatuses");
const interval = 5000;
const useStore = (api) => {
const [state, setState] = react_1.useState({
data: null,
loading: true,
});
const selectedStatuses = useSelectedStatuses_1.useSelectedStatuses();
const update = () => api
.getQueues({ status: selectedStatuses })
.then((data) => {
setState({ data, loading: false });
})
// eslint-disable-next-line no-console
.catch((error) => console.error('Failed to poll', error));
useInterval_1.useInterval(update, interval, [selectedStatuses]);
const promoteJob = (queueName) => (job) => () => api.promoteJob(queueName, job.id).then(update);
const retryJob = (queueName) => (job) => () => api.retryJob(queueName, job.id).then(update);
const cleanJob = (queueName) => (job) => () => api.cleanJob(queueName, job.id).then(update);
const retryAll = (queueName) => () => api.retryAll(queueName).then(update);
const cleanAllDelayed = (queueName) => () => api.cleanAllDelayed(queueName).then(update);
const cleanAllFailed = (queueName) => () => api.cleanAllFailed(queueName).then(update);
const cleanAllCompleted = (queueName) => () => api.cleanAllCompleted(queueName).then(update);
const getJobLogs = (queueName) => (job) => () => api.getJobLogs(queueName, job.id);
return {
state,
actions: {
promoteJob,
retryJob,
retryAll,
cleanJob,
cleanAllDelayed,
cleanAllFailed,
cleanAllCompleted,
getJobLogs,
},
selectedStatuses,
};
};
exports.useStore = useStore;
//# sourceMappingURL=useStore.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"useStore.js","sourceRoot":"","sources":["../../../src/ui/hooks/useStore.ts"],"names":[],"mappings":";;;AAAA,iCAAgC;AAIhC,+CAA2C;AAC3C,+DAA2D;AAE3D,MAAM,QAAQ,GAAG,IAAI,CAAA;AAad,MAAM,QAAQ,GAAG,CAAC,GAAQ,EAAS,EAAE;IAC1C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,gBAAQ,CAAQ;QACxC,IAAI,EAAE,IAAI;QACV,OAAO,EAAE,IAAI;KACd,CAAC,CAAA;IAEF,MAAM,gBAAgB,GAAG,yCAAmB,EAAE,CAAA;IAE9C,MAAM,MAAM,GAAG,GAAG,EAAE,CAClB,GAAG;SACA,SAAS,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;SACvC,IAAI,CAAC,CAAC,IAAmB,EAAE,EAAE;QAC5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;IACpC,CAAC,CAAC;QACF,sCAAsC;SACrC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC,CAAA;IAE7D,yBAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAA;IAEjD,MAAM,UAAU,GAAG,CAAC,SAAiB,EAAE,EAAE,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG,EAAE,CAC9D,GAAG,CAAC,UAAU,CAAC,SAAS,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAEhD,MAAM,QAAQ,GAAG,CAAC,SAAiB,EAAE,EAAE,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG,EAAE,CAC5D,GAAG,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAE9C,MAAM,QAAQ,GAAG,CAAC,SAAiB,EAAE,EAAE,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG,EAAE,CAC5D,GAAG,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAE9C,MAAM,QAAQ,GAAG,CAAC,SAAiB,EAAE,EAAE,CAAC,GAAG,EAAE,CAC3C,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAEtC,MAAM,eAAe,GAAG,CAAC,SAAiB,EAAE,EAAE,CAAC,GAAG,EAAE,CAClD,GAAG,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAE7C,MAAM,cAAc,GAAG,CAAC,SAAiB,EAAE,EAAE,CAAC,GAAG,EAAE,CACjD,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAE5C,MAAM,iBAAiB,GAAG,CAAC,SAAiB,EAAE,EAAE,CAAC,GAAG,EAAE,CACpD,GAAG,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAE/C,MAAM,UAAU,GAAG,CAAC,SAAiB,EAAE,EAAE,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG,EAAE,CAC9D,GAAG,CAAC,UAAU,CAAC,SAAS,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;IAEnC,OAAO;QACL,KAAK;QACL,OAAO,EAAE;YACP,UAAU;YACV,QAAQ;YACR,QAAQ;YACR,QAAQ;YACR,eAAe;YACf,cAAc;YACd,iBAAiB;YACjB,UAAU;SACX;QACD,gBAAgB;KACjB,CAAA;AACH,CAAC,CAAA;AAzDY,QAAA,QAAQ,YAyDpB"}
+3
View File
@@ -0,0 +1,3 @@
import './index.css';
import './theme.css';
import './toastify.css';
+1
View File
@@ -0,0 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><base href="<%= basePath %>"/><title>Bull Dashboard</title><link href="https://fonts.googleapis.com/css2?family=Ubuntu:wght@300;400;500&display=swap" rel="stylesheet"><script defer="defer" src="<%= basePath %>/static/vendor.a7a5c6b037a450ac3f38.js"></script><script defer="defer" src="<%= basePath %>/static/main.b9ee2f393232badbddf2.js"></script><link href="<%= basePath %>/static/main.776d169b005873942466.css" rel="stylesheet"></head><body><div id="root">Loading...</div></body></html>
+19
View File
@@ -0,0 +1,19 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = __importDefault(require("react"));
const react_dom_1 = require("react-dom");
require("./index.css");
require("./theme.css");
require("./toastify.css");
const react_router_dom_1 = require("react-router-dom");
const App_1 = require("./components/App");
const Api_1 = require("./services/Api");
const basePath = ((_a = document.head.querySelector('base')) === null || _a === void 0 ? void 0 : _a.getAttribute('href')) || '';
const api = new Api_1.Api({ basePath });
react_dom_1.render(react_1.default.createElement(react_router_dom_1.BrowserRouter, { basename: basePath },
react_1.default.createElement(App_1.App, { api: api })), document.getElementById('root'));
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AACzB,yCAAkC;AAElC,uBAAoB;AACpB,uBAAoB;AACpB,0BAAuB;AACvB,uDAAgD;AAChD,0CAAsC;AACtC,wCAAoC;AAEpC,MAAM,QAAQ,GAAG,CAAA,MAAA,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,0CAAE,YAAY,CAAC,MAAM,CAAC,KAAI,EAAE,CAAA;AAChF,MAAM,GAAG,GAAG,IAAI,SAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAA;AAEjC,kBAAM,CACJ,8BAAC,gCAAa,IAAC,QAAQ,EAAE,QAAQ;IAC/B,8BAAC,SAAG,IAAC,GAAG,EAAE,GAAG,GAAI,CACH,EAChB,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAChC,CAAA"}
+21
View File
@@ -0,0 +1,21 @@
import { GetQueues } from '../../@types/api';
import { SelectedStatuses } from '../../@types/app';
export declare class Api {
private axios;
constructor({ basePath }?: {
basePath: string;
});
getQueues({ status, }: {
status: SelectedStatuses;
}): Promise<GetQueues>;
retryAll(queueName: string): Promise<void>;
cleanAllDelayed(queueName: string): Promise<void>;
cleanAllFailed(queueName: string): Promise<void>;
cleanAllCompleted(queueName: string): Promise<void>;
cleanJob(queueName: string, jobId: string | number | undefined): Promise<void>;
retryJob(queueName: string, jobId: string | number | undefined): Promise<void>;
promoteJob(queueName: string, jobId: string | number | undefined): Promise<void>;
getJobLogs(queueName: string, jobId: string | number | undefined): Promise<string[]>;
private handleResponse;
private handleError;
}
+53
View File
@@ -0,0 +1,53 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Api = void 0;
const axios_1 = __importDefault(require("axios"));
const react_toastify_1 = require("react-toastify");
class Api {
constructor({ basePath } = { basePath: '' }) {
this.axios = axios_1.default.create({ baseURL: `${basePath}/api` });
this.axios.interceptors.response.use(this.handleResponse, this.handleError);
}
getQueues({ status, }) {
return this.axios.get(`/queues/`, { params: { ...status } });
}
retryAll(queueName) {
return this.axios.put(`/queues/${encodeURIComponent(queueName)}/retry`);
}
cleanAllDelayed(queueName) {
return this.axios.put(`/queues/${encodeURIComponent(queueName)}/clean/delayed`);
}
cleanAllFailed(queueName) {
return this.axios.put(`/queues/${encodeURIComponent(queueName)}/clean/failed`);
}
cleanAllCompleted(queueName) {
return this.axios.put(`/queues/${encodeURIComponent(queueName)}/clean/completed`);
}
cleanJob(queueName, jobId) {
return this.axios.put(`/queues/${encodeURIComponent(queueName)}/${jobId}/clean`);
}
retryJob(queueName, jobId) {
return this.axios.put(`/queues/${encodeURIComponent(queueName)}/${jobId}/retry`);
}
promoteJob(queueName, jobId) {
return this.axios.put(`/queues/${encodeURIComponent(queueName)}/${jobId}/promote`);
}
getJobLogs(queueName, jobId) {
return this.axios.get(`/queues/${encodeURIComponent(queueName)}/${jobId}/logs`);
}
handleResponse(response) {
return response.data;
}
async handleError(error) {
var _a, _b;
if ((_a = error.response.data) === null || _a === void 0 ? void 0 : _a.error) {
react_toastify_1.toast.error((_b = error.response.data) === null || _b === void 0 ? void 0 : _b.error, { autoClose: 5000 });
}
return Promise.resolve(error.response.data);
}
}
exports.Api = Api;
//# sourceMappingURL=Api.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"Api.js","sourceRoot":"","sources":["../../../src/ui/services/Api.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA2D;AAC3D,mDAAsC;AAItC,MAAa,GAAG;IAGd,YAAY,EAAE,QAAQ,KAA2B,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC/D,IAAI,CAAC,KAAK,GAAG,eAAK,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,QAAQ,MAAM,EAAE,CAAC,CAAA;QACzD,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;IAC7E,CAAC;IAEM,SAAS,CAAC,EACf,MAAM,GAGP;QACC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,EAAE,CAAC,CAAA;IAC9D,CAAC;IAEM,QAAQ,CAAC,SAAiB;QAC/B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,kBAAkB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;IACzE,CAAC;IAEM,eAAe,CAAC,SAAiB;QACtC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CACnB,WAAW,kBAAkB,CAAC,SAAS,CAAC,gBAAgB,CACzD,CAAA;IACH,CAAC;IAEM,cAAc,CAAC,SAAiB;QACrC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CACnB,WAAW,kBAAkB,CAAC,SAAS,CAAC,eAAe,CACxD,CAAA;IACH,CAAC;IAEM,iBAAiB,CAAC,SAAiB;QACxC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CACnB,WAAW,kBAAkB,CAAC,SAAS,CAAC,kBAAkB,CAC3D,CAAA;IACH,CAAC;IAEM,QAAQ,CACb,SAAiB,EACjB,KAAkC;QAElC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CACnB,WAAW,kBAAkB,CAAC,SAAS,CAAC,IAAI,KAAK,QAAQ,CAC1D,CAAA;IACH,CAAC;IAEM,QAAQ,CACb,SAAiB,EACjB,KAAkC;QAElC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CACnB,WAAW,kBAAkB,CAAC,SAAS,CAAC,IAAI,KAAK,QAAQ,CAC1D,CAAA;IACH,CAAC;IAEM,UAAU,CACf,SAAiB,EACjB,KAAkC;QAElC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CACnB,WAAW,kBAAkB,CAAC,SAAS,CAAC,IAAI,KAAK,UAAU,CAC5D,CAAA;IACH,CAAC;IAEM,UAAU,CACf,SAAiB,EACjB,KAAkC;QAElC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CACnB,WAAW,kBAAkB,CAAC,SAAS,CAAC,IAAI,KAAK,OAAO,CACzD,CAAA;IACH,CAAC;IAEO,cAAc,CAAC,QAAuB;QAC5C,OAAO,QAAQ,CAAC,IAAI,CAAA;IACtB,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,KAAkC;;QAC1D,IAAI,MAAA,KAAK,CAAC,QAAQ,CAAC,IAAI,0CAAE,KAAK,EAAE;YAC9B,sBAAK,CAAC,KAAK,CAAC,MAAA,KAAK,CAAC,QAAQ,CAAC,IAAI,0CAAE,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;SAC7D;QAED,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC7C,CAAC;CACF;AArFD,kBAqFC"}