Project depdendencies set up to handle tailwind styles inside storybook. Set up dto handlers
This commit is contained in:
parent
641c6d60e5
commit
03b58983e1
@ -1,9 +1,68 @@
|
|||||||
export const parameters = {
|
import "../src/index.css";
|
||||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
/**
|
||||||
controls: {
|
* Read https://storybook.js.org/docs/react/configure/overview#configure-story-rendering
|
||||||
matchers: {
|
* for more information about the purpose of this file.
|
||||||
color: /(background|color)$/i,
|
*
|
||||||
date: /Date$/,
|
* Use preview.js for global code (such as CSS imports or JavaScript mocks)
|
||||||
},
|
* that applies to all stories. For example, `import thirdPartyCss.css`.
|
||||||
},
|
*
|
||||||
}
|
* This file can have three exports:
|
||||||
|
* - decorators - an array of global decorators
|
||||||
|
* - parameters - an object of global parameters
|
||||||
|
* - globalTypes - definition of globalTypes
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorators
|
||||||
|
*
|
||||||
|
* A decorator is a way to wrap a story in extra “rendering” functionality.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* import React from 'react';
|
||||||
|
* export const decorators = [(Story) => <div style={{ margin: '3em' }}><Story/></div>];
|
||||||
|
*
|
||||||
|
* Each story throughout the library will be wrapped in a div with a margin of 3
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameters
|
||||||
|
*
|
||||||
|
* Most Storybook addons are configured via a parameter-based API.
|
||||||
|
* You can set global parameters in this file
|
||||||
|
*
|
||||||
|
* export const parameters = {
|
||||||
|
* backgrounds: {
|
||||||
|
* values: [
|
||||||
|
* { name: 'red', value: '#f00' },
|
||||||
|
* { name: 'green', value: '#0f0' },
|
||||||
|
* ],
|
||||||
|
* },
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* With backgrounds, you configure the list of backgrounds that every story can render in.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global Types
|
||||||
|
*
|
||||||
|
* Global Types allow you to add your own toolbars by creating
|
||||||
|
* globalTypes with a toolbar annotation:
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
*
|
||||||
|
* export const globalTypes = {
|
||||||
|
* theme: {
|
||||||
|
* name: 'Theme',
|
||||||
|
* description: 'Global theme for components',
|
||||||
|
* defaultValue: 'light',
|
||||||
|
* toolbar: {
|
||||||
|
* icon: 'circlehollow',
|
||||||
|
* // array of plain string values or MenuItem shape
|
||||||
|
* items: ['light', 'dark'],
|
||||||
|
* },
|
||||||
|
* },
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* Will add a new dropdown in your toolbar with options light and dark.
|
||||||
|
**/
|
||||||
|
17301
package-lock.json
generated
17301
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
59
package.json
59
package.json
@ -1,32 +1,32 @@
|
|||||||
{
|
{
|
||||||
"name": "test",
|
"name": "freeland",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/react": "^1.5.0",
|
"@headlessui/react": "^1.6.6",
|
||||||
"@react-keycloak/web": "^3.4.0",
|
"@reduxjs/toolkit": "^1.8.3",
|
||||||
"@reduxjs/toolkit": "^1.8.1",
|
"@types/node": "^16.11.47",
|
||||||
"axios": "^0.26.1",
|
"@types/react": "^18.0.15",
|
||||||
|
"@types/react-dom": "^18.0.6",
|
||||||
|
"axios": "^0.27.2",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
"cross-env": "^7.0.3",
|
|
||||||
"formik": "^2.2.9",
|
"formik": "^2.2.9",
|
||||||
"graphql": "^16.4.0",
|
"graphql": "^16.5.0",
|
||||||
"graphql-tag": "^2.12.6",
|
"graphql-tag": "^2.12.6",
|
||||||
"i18next": "^21.6.16",
|
"i18next": "^21.8.16",
|
||||||
"i18next-browser-languagedetector": "^6.1.4",
|
"i18next-browser-languagedetector": "^6.1.4",
|
||||||
"i18next-http-backend": "^1.4.0",
|
"i18next-http-backend": "^1.4.1",
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"keycloak-js": "^18.0.0",
|
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lodash.debounce": "^4.0.8",
|
"react": "^18.2.0",
|
||||||
"react": "^18.0.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-dom": "^18.0.0",
|
|
||||||
"react-hotkeys": "^2.0.0",
|
"react-hotkeys": "^2.0.0",
|
||||||
"react-i18next": "^11.16.7",
|
"react-i18next": "^11.18.3",
|
||||||
"react-redux": "^7.2.8",
|
"react-redux": "^8.0.2",
|
||||||
"react-router-dom": "^6.3.0",
|
"react-router-dom": "^6.3.0",
|
||||||
"react-scripts": "5.0.0",
|
"react-scripts": "5.0.1",
|
||||||
"react-scrollbars-custom": "^4.0.27",
|
"react-scrollbars-custom": "^4.1.0",
|
||||||
|
"typescript": "^4.7.4",
|
||||||
"web-vitals": "^2.1.4",
|
"web-vitals": "^2.1.4",
|
||||||
"yup": "^0.32.11"
|
"yup": "^0.32.11"
|
||||||
},
|
},
|
||||||
@ -45,6 +45,14 @@
|
|||||||
"react-app/jest"
|
"react-app/jest"
|
||||||
],
|
],
|
||||||
"overrides": [
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"**/*.stories.*"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"import/no-anonymous-default-export": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"files": [
|
"files": [
|
||||||
"**/*.stories.*"
|
"**/*.stories.*"
|
||||||
@ -68,6 +76,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@babel/preset-typescript": "^7.18.6",
|
||||||
"@storybook/addon-actions": "^6.5.9",
|
"@storybook/addon-actions": "^6.5.9",
|
||||||
"@storybook/addon-essentials": "^6.5.9",
|
"@storybook/addon-essentials": "^6.5.9",
|
||||||
"@storybook/addon-interactions": "^6.5.9",
|
"@storybook/addon-interactions": "^6.5.9",
|
||||||
@ -79,22 +88,16 @@
|
|||||||
"@storybook/react": "^6.5.9",
|
"@storybook/react": "^6.5.9",
|
||||||
"@storybook/testing-library": "^0.0.13",
|
"@storybook/testing-library": "^0.0.13",
|
||||||
"@testing-library/jest-dom": "^5.16.4",
|
"@testing-library/jest-dom": "^5.16.4",
|
||||||
"@testing-library/react": "^12.1.4",
|
"@testing-library/react": "^13.3.0",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
"@types/jest": "^27.4.1",
|
"@types/jest": "^27.5.2",
|
||||||
"@types/lodash.debounce": "^4.0.6",
|
"autoprefixer": "^10.4.8",
|
||||||
"@types/node": "^16.11.26",
|
|
||||||
"@types/react": "^17.0.44",
|
|
||||||
"@types/react-dom": "^17.0.15",
|
|
||||||
"@types/react-redux": "^7.1.23",
|
|
||||||
"autoprefixer": "^10.4.4",
|
|
||||||
"babel-plugin-named-exports-order": "^0.0.2",
|
"babel-plugin-named-exports-order": "^0.0.2",
|
||||||
"jest": "^28.1.3",
|
"jest": "^28.1.3",
|
||||||
"postcss": "^8.4.12",
|
"postcss": "^8.4.14",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"react-test-renderer": "^18.2.0",
|
"react-test-renderer": "^18.2.0",
|
||||||
"tailwindcss": "^3.0.23",
|
"tailwindcss": "^3.1.7",
|
||||||
"typescript": "^4.6.3",
|
|
||||||
"webpack": "^5.74.0"
|
"webpack": "^5.74.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import _ from "lodash";
|
||||||
export interface DTOModel<T extends {} | undefined> {
|
export interface DTOModel<T extends {} | undefined> {
|
||||||
status: number;
|
status: number;
|
||||||
type: string;
|
type: string;
|
||||||
@ -15,4 +16,16 @@ export interface GraphQLFailureDTO {
|
|||||||
errors: {code: string, message: string, name: string}[]
|
errors: {code: string, message: string, name: string}[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isDTOModel(obj: any): obj is DTOModel<any> {
|
||||||
|
return obj !== null && typeof obj === "object" && !!obj.isDTOModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isDTO = (obj: any): obj is DTOModel<any> => obj.data !== null &&
|
||||||
|
_.isObject(obj.data) &&
|
||||||
|
_.has(obj.data, "status") &&
|
||||||
|
_.has(obj.data, "type") &&
|
||||||
|
_.has(obj.data, "message") &&
|
||||||
|
_.has(obj.data, "description") &&
|
||||||
|
_.has(obj.data, "data")
|
||||||
|
|
||||||
export const GRAPHQL_UNAUTHORIZED_KEY = "UNAUTHENTICATED";
|
export const GRAPHQL_UNAUTHORIZED_KEY = "UNAUTHENTICATED";
|
@ -1,7 +1,6 @@
|
|||||||
import { AxiosError } from "axios";
|
import { AxiosError } from "axios";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { DTOModel } from "./dto_model";
|
import { DTOModel, isDTO } from "./dto_model";
|
||||||
|
|
||||||
|
|
||||||
export interface FailureI {
|
export interface FailureI {
|
||||||
status?: number;
|
status?: number;
|
||||||
@ -26,53 +25,75 @@ class Failure implements FailureI {
|
|||||||
static isf = true;
|
static isf = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {Failure} o
|
* @param {Failure} o
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
static isFailure(o: any): o is Failure {
|
static isFailure(o: any): o is Failure {
|
||||||
if(!_.isObjectLike(o)) return false;
|
if (!_.isObjectLike(o)) return false;
|
||||||
if(_.has(o, 'message')) return true;
|
if (_.has(o, "message")) return true;
|
||||||
return false;
|
return false;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
constructor({ status, message, key, meta }: FailureI) {
|
constructor({ status, message, key, meta }: FailureI) {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.meta = meta;
|
this.meta = meta;
|
||||||
console.error([key ?? '', message].filter((i) => i.length !== 0).join(':'));
|
console.error([key ?? "", message].filter((i) => i.length !== 0).join(":"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromReason(reason: AxiosError<DTOModel<any>>, key?: string): Failure {
|
static fromReason(reason: AxiosError<any, any>, key?: string): Failure {
|
||||||
if (reason.response) {
|
|
||||||
|
try {
|
||||||
|
if(!Failure.verifyContainsDTO(reason)) {
|
||||||
|
throw reason;
|
||||||
|
}
|
||||||
|
if (reason.response) {
|
||||||
|
return new Failure({
|
||||||
|
status: reason.response!.status,
|
||||||
|
message:
|
||||||
|
reason.response!.data.message ?? "Unknown response error model",
|
||||||
|
key: key,
|
||||||
|
meta: {
|
||||||
|
isRequestFailure: true,
|
||||||
|
data: reason.response.data,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (reason.request) {
|
||||||
|
return new Failure({
|
||||||
|
message: `Something went wrong while ${reason.config.url} had been called`,
|
||||||
|
key: `unreachedResponse(${key})`,
|
||||||
|
meta: {
|
||||||
|
isNetworkFailure: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
throw reason;
|
||||||
|
} catch (error) {
|
||||||
return new Failure({
|
return new Failure({
|
||||||
status: reason.response!.status,
|
message: reason.message,
|
||||||
message:
|
|
||||||
reason.response!.data.message ?? "Unknown response error model",
|
|
||||||
key: key,
|
key: key,
|
||||||
meta: {
|
meta: { isPlainFailure: true },
|
||||||
isRequestFailure: true,
|
|
||||||
data: reason.response.data,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (reason.request) {
|
}
|
||||||
return new Failure({
|
|
||||||
message: `Something went wrong while ${reason.config.url} had been called`,
|
/**
|
||||||
key: `unreachedResponse(${key})`,
|
* Verifies that passed object matches [DTOModel] structure
|
||||||
meta: {
|
*
|
||||||
isNetworkFailure: true,
|
* Otherwise it will rethrow passed object
|
||||||
},
|
*/
|
||||||
});
|
static verifyContainsDTO(
|
||||||
}
|
reason: AxiosError<any, any>
|
||||||
return new Failure({
|
): reason is AxiosError<DTOModel<any>, any> {
|
||||||
message: reason.message,
|
return [reason.response, reason.request].reduce((acc, obj) => {
|
||||||
key: key,
|
if (acc || isDTO(obj)) {
|
||||||
meta: { isPlainFailure: true },
|
return true;
|
||||||
});
|
}
|
||||||
|
return false;
|
||||||
|
}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(): string {
|
toString(): string {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* Libraries */
|
/* Libraries */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
import React, { useEffect } from "react";
|
import React from "react";
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* Misc */
|
/* Misc */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
@ -48,7 +48,7 @@ export default function Dashboard() {
|
|||||||
hasSubscription,
|
hasSubscription,
|
||||||
} = useSubscriptionsViewModel(subscriptionsStore, uiStore);
|
} = useSubscriptionsViewModel(subscriptionsStore, uiStore);
|
||||||
/* ---------------------------------- Hooks --------------------------------- */
|
/* ---------------------------------- Hooks --------------------------------- */
|
||||||
const Wrapper: React.FC = React.useMemo(
|
const Wrapper: React.FC<Omit<React.ComponentPropsWithoutRef<"div">, "">> = React.useMemo(
|
||||||
() => (props) =>
|
() => (props) =>
|
||||||
(
|
(
|
||||||
<div className="grid grid-cols-4 grid-rows-none gap-x-8 gap-y-8">
|
<div className="grid grid-cols-4 grid-rows-none gap-x-8 gap-y-8">
|
||||||
@ -90,7 +90,7 @@ export default function Dashboard() {
|
|||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
[]
|
[navigate]
|
||||||
);
|
);
|
||||||
/* --------------------------------- Markup --------------------------------- */
|
/* --------------------------------- Markup --------------------------------- */
|
||||||
if (subscriptionsLoading) {
|
if (subscriptionsLoading) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import debounce from "lodash.debounce";
|
import {debounce} from "lodash";
|
||||||
import { User } from "../domain/userEntity";
|
import { User } from "../domain/userEntity";
|
||||||
import { updateUser } from "../domain/userModel";
|
import { updateUser } from "../domain/userModel";
|
||||||
import { UserStore } from "../domain/userStore";
|
import { UserStore } from "../domain/userStore";
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import Failure from "core/failure";
|
import Failure from "core/failure";
|
||||||
import debounce from "lodash.debounce";
|
import {debounce} from "lodash";
|
||||||
import { UpdateUserArtifacts } from "user/domain/userModel";
|
import { UpdateUserArtifacts } from "user/domain/userModel";
|
||||||
import { User } from "../domain/userEntity";
|
import { User } from "../domain/userEntity";
|
||||||
import { UserStore } from "../domain/userStore";
|
import { UserStore } from "../domain/userStore";
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"lib": [
|
"lib": [
|
||||||
"dom",
|
"dom",
|
||||||
"dom.iterable",
|
"dom.iterable",
|
||||||
"esnext"
|
"esnext",
|
||||||
],
|
],
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
@ -19,9 +19,14 @@
|
|||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"baseUrl": "./src",
|
"baseUrl": "src",
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src",
|
"src/**/*",
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"storybook-static",
|
||||||
|
"src/**/*.stories.tsx",
|
||||||
|
"src/**/*.test.tsx"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user