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"}