refactor: setup prettier as formatter for the whole monorepo (#26)
This commit is contained in:
@@ -1,33 +1,33 @@
|
||||
{
|
||||
"name": "GitHub Readme Stats Dev",
|
||||
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/node:1": { "version": "22" }
|
||||
},
|
||||
"forwardPorts": [3000],
|
||||
"portsAttributes": {
|
||||
"3000": { "label": "HTTP" }
|
||||
},
|
||||
"appPort": [],
|
||||
"name": "GitHub Readme Stats Dev",
|
||||
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/node:1": { "version": "22" }
|
||||
},
|
||||
"forwardPorts": [3000],
|
||||
"portsAttributes": {
|
||||
"3000": { "label": "HTTP" }
|
||||
},
|
||||
"appPort": [],
|
||||
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
"postCreateCommand": "npm install -g vercel",
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
"postCreateCommand": "npm install -g vercel",
|
||||
|
||||
// Use 'postStartCommand' to run commands after the container is started.
|
||||
"postStartCommand": "hostname dev && npm install",
|
||||
// Use 'postStartCommand' to run commands after the container is started.
|
||||
"postStartCommand": "hostname dev && npm install",
|
||||
|
||||
// Configure tool-specific properties.
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"yzhang.markdown-all-in-one",
|
||||
"esbenp.prettier-vscode",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"github.vscode-github-actions"
|
||||
]
|
||||
}
|
||||
},
|
||||
// Configure tool-specific properties.
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"yzhang.markdown-all-in-one",
|
||||
"esbenp.prettier-vscode",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"github.vscode-github-actions"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"remoteUser": "root",
|
||||
"privileged": true
|
||||
"remoteUser": "root",
|
||||
"privileged": true
|
||||
}
|
||||
|
||||
+2
-4
@@ -37,11 +37,9 @@ jobs:
|
||||
close_comment:
|
||||
Closing this issue because it appears to be empty. Please update the
|
||||
issue for it to be reopened.
|
||||
open_comment:
|
||||
Reopening this issue because the author provided more information.
|
||||
open_comment: Reopening this issue because the author provided more information.
|
||||
check_templates: true
|
||||
template_close_comment:
|
||||
Closing this issue since the issue template was not filled in.
|
||||
Please provide us with more information to have this issue reopened.
|
||||
template_open_comment:
|
||||
Reopening this issue because the author provided more information.
|
||||
template_open_comment: Reopening this issue because the author provided more information.
|
||||
|
||||
+1
-2
@@ -59,8 +59,7 @@ jobs:
|
||||
branch: "update_langs/patch"
|
||||
delete-branch: true
|
||||
title: Update languages JSON
|
||||
body:
|
||||
"The
|
||||
body: "The
|
||||
[update-langs](https://github.com/anuraghazra/github-readme-stats/actions/workflows/update-langs.yaml)
|
||||
action found new/updated languages in the [upstream languages JSON
|
||||
file](https://raw.githubusercontent.com/github/linguist/master/lib/linguist/languages.yml)."
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
22
|
||||
@@ -1,5 +0,0 @@
|
||||
node_modules
|
||||
*.json
|
||||
*.md
|
||||
coverage
|
||||
.vercel
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"trailingComma": "all",
|
||||
"useTabs": false,
|
||||
"endOfLine": "auto",
|
||||
"proseWrap": "always"
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
.devcontainer
|
||||
.github
|
||||
.husky
|
||||
.vscode
|
||||
benchmarks
|
||||
coverage
|
||||
scripts
|
||||
@@ -10,6 +8,4 @@ tests
|
||||
**/*.md
|
||||
**/*.svg
|
||||
.eslintrc.json
|
||||
.prettierignore
|
||||
.pretterrc.json
|
||||
codecov.yml
|
||||
|
||||
Vendored
-9
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"yzhang.markdown-all-in-one",
|
||||
"esbenp.prettier-vscode",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"ms-azuretools.vscode-containers",
|
||||
"github.vscode-github-actions"
|
||||
]
|
||||
}
|
||||
Vendored
-8
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"markdown.extension.toc.levels": "1..3",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"[javascript]": {
|
||||
"editor.tabSize": 2
|
||||
}
|
||||
}
|
||||
@@ -2,4 +2,4 @@
|
||||
"expiration": 39600,
|
||||
"bypassToken": "r3fr3shT0k3n-r3fr3shT0k3n-r3fr3shT0k3n",
|
||||
"passQuery": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
"expiration": 39600,
|
||||
"bypassToken": "r3fr3shT0k3n-r3fr3shT0k3n-r3fr3shT0k3n",
|
||||
"passQuery": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
"expiration": 39600,
|
||||
"bypassToken": "r3fr3shT0k3n-r3fr3shT0k3n-r3fr3shT0k3n",
|
||||
"passQuery": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
"expiration": 39600,
|
||||
"bypassToken": "r3fr3shT0k3n-r3fr3shT0k3n-r3fr3shT0k3n",
|
||||
"passQuery": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
"expiration": 39600,
|
||||
"bypassToken": "r3fr3shT0k3n-r3fr3shT0k3n-r3fr3shT0k3n",
|
||||
"passQuery": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,10 +53,10 @@ export default async (req, res) => {
|
||||
},
|
||||
);
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
res.statusCode = 500;
|
||||
res.send("Failed to delete GitHub authorization with private access");
|
||||
return;
|
||||
logger.error(err);
|
||||
res.statusCode = 500;
|
||||
res.send("Failed to delete GitHub authorization with private access");
|
||||
return;
|
||||
}
|
||||
|
||||
await deleteUser(user_key);
|
||||
@@ -68,6 +68,9 @@ export default async (req, res) => {
|
||||
}).toString();
|
||||
|
||||
res.statusCode = 302;
|
||||
res.setHeader("Location", `https://github.com/login/oauth/authorize?${params}`);
|
||||
res.setHeader(
|
||||
"Location",
|
||||
`https://github.com/login/oauth/authorize?${params}`,
|
||||
);
|
||||
res.end();
|
||||
};
|
||||
|
||||
@@ -94,19 +94,18 @@ export default async (req, res) => {
|
||||
(owner && !safePattern.test(owner))
|
||||
) {
|
||||
return res.send(
|
||||
renderError(
|
||||
{
|
||||
message: "Something went wrong",
|
||||
secondaryMessage: "Username, repository or owner contains unsafe characters",
|
||||
renderOptions: {
|
||||
title_color,
|
||||
text_color,
|
||||
bg_color,
|
||||
border_color,
|
||||
theme,
|
||||
},
|
||||
renderError({
|
||||
message: "Something went wrong",
|
||||
secondaryMessage:
|
||||
"Username, repository or owner contains unsafe characters",
|
||||
renderOptions: {
|
||||
title_color,
|
||||
text_color,
|
||||
bg_color,
|
||||
border_color,
|
||||
theme,
|
||||
},
|
||||
),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -124,7 +123,7 @@ export default async (req, res) => {
|
||||
parseBoolean(include_all_commits),
|
||||
parseArray(exclude_repo),
|
||||
showStats.includes("prs_merged") ||
|
||||
showStats.includes("prs_merged_percentage"),
|
||||
showStats.includes("prs_merged_percentage"),
|
||||
showStats.includes("discussions_started"),
|
||||
showStats.includes("discussions_answered"),
|
||||
parseInt(commits_year, 10),
|
||||
@@ -147,7 +146,9 @@ export default async (req, res) => {
|
||||
setCacheHeaders(res, cacheSeconds);
|
||||
|
||||
return res.send(
|
||||
renderStatsCard(stats, {
|
||||
renderStatsCard(
|
||||
stats,
|
||||
{
|
||||
hide: parseArray(hide),
|
||||
show_icons: parseBoolean(show_icons),
|
||||
hide_title: parseBoolean(hide_title),
|
||||
|
||||
@@ -18,7 +18,7 @@ export default async (req, res) => {
|
||||
|
||||
res.send({
|
||||
privateAccess: result.privateAccess,
|
||||
token: result.token
|
||||
token: result.token,
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
"preview-theme": "node scripts/preview-theme",
|
||||
"close-stale-theme-prs": "node scripts/close-stale-theme-prs",
|
||||
"generate-langs-json": "node scripts/generate-langs-json",
|
||||
"format": "prettier --write .",
|
||||
"format:check": "prettier --check .",
|
||||
"lint": "npx eslint --max-warnings 0 \"./src/**/*.js\" \"./scripts/**/*.js\" \"./tests/**/*.js\" \"./api-renamed/**/*.js\" \"./themes/**/*.js\"",
|
||||
"bench": "node --experimental-vm-modules node_modules/jest/bin/jest.js --config jest.bench.config.js"
|
||||
},
|
||||
|
||||
@@ -14,7 +14,6 @@ import { icons } from "../common/icons.js";
|
||||
import languageColors from "../common/languageColors.json" with { type: "json" };
|
||||
import { parseEmojis } from "../common/ops.js";
|
||||
|
||||
|
||||
const ICON_SIZE = 16;
|
||||
const CARD_DEFAULT_WIDTH = 400;
|
||||
const HEADER_MAX_LENGTH = 35;
|
||||
|
||||
@@ -378,7 +378,8 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
|
||||
// @ts-ignore
|
||||
progressBarColor: titleColor,
|
||||
// @ts-ignore
|
||||
progressBarBackgroundColor: textColor === titleColor ? bgColor : textColor,
|
||||
progressBarBackgroundColor:
|
||||
textColor === titleColor ? bgColor : textColor,
|
||||
hideProgress: hide_progress,
|
||||
progressBarWidth: normalizedWidth - TOTAL_TEXT_WIDTH,
|
||||
});
|
||||
|
||||
@@ -83,7 +83,8 @@ const getCardColors = ({
|
||||
theme,
|
||||
}) => {
|
||||
const defaultTheme = themes["default"];
|
||||
const isThemeProvided = theme !== null && theme !== undefined && theme in themes;
|
||||
const isThemeProvided =
|
||||
theme !== null && theme !== undefined && theme in themes;
|
||||
|
||||
// @ts-ignore
|
||||
const selectedTheme = isThemeProvided ? themes[theme] : defaultTheme;
|
||||
|
||||
@@ -215,7 +215,7 @@ export async function getUserAccessByKey(userKey) {
|
||||
}
|
||||
return {
|
||||
token: rows[0].access_token,
|
||||
privateAccess: rows[0].private_access
|
||||
privateAccess: rows[0].private_access,
|
||||
};
|
||||
} catch (err) {
|
||||
if (err.code === "42P01") {
|
||||
@@ -250,7 +250,7 @@ export async function getUserAccessByName(userName) {
|
||||
}
|
||||
return {
|
||||
token: rows[0].access_token,
|
||||
privateAccess: rows[0].private_access
|
||||
privateAccess: rows[0].private_access,
|
||||
};
|
||||
} catch (err) {
|
||||
if (err.code === "42P01") {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,10 +5,7 @@ import * as dotenv from "dotenv";
|
||||
import githubUsernameRegex from "github-username-regex";
|
||||
import { calculateRank } from "../calculateRank.js";
|
||||
import { retryer } from "../common/retryer.js";
|
||||
import {
|
||||
buildSearchFilter,
|
||||
parseOwnerAffiliations,
|
||||
} from "../common/ops.js";
|
||||
import { buildSearchFilter, parseOwnerAffiliations } from "../common/ops.js";
|
||||
import { logger } from "../common/log.js";
|
||||
import { excludeRepositories } from "../common/envs.js";
|
||||
import { CustomError, MissingParamError } from "../common/error.js";
|
||||
@@ -191,10 +188,7 @@ const fetchTotalItems = (variables, token) => {
|
||||
`https://api.github.com/search/` +
|
||||
variables.type +
|
||||
`?per_page=1&q=` +
|
||||
buildSearchFilter(variables.repo, variables.owner).replaceAll(
|
||||
" ",
|
||||
"+",
|
||||
) +
|
||||
buildSearchFilter(variables.repo, variables.owner).replaceAll(" ", "+") +
|
||||
variables.filter,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
||||
@@ -73,7 +73,10 @@ const fetchTopLanguages = async (
|
||||
}
|
||||
ownerAffiliations = parseOwnerAffiliations(ownerAffiliations);
|
||||
|
||||
const res = await retryer(fetcher, username, { login: username, ownerAffiliations });
|
||||
const res = await retryer(fetcher, username, {
|
||||
login: username,
|
||||
ownerAffiliations,
|
||||
});
|
||||
|
||||
if (res.data.errors) {
|
||||
logger.error(res.data.errors);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"$schema": "https://openapi.vercel.sh/vercel.json",
|
||||
"buildCommand": "pnpm install && ../../vercel-preparation.sh",
|
||||
"redirects": [
|
||||
{
|
||||
@@ -12,4 +13,4 @@
|
||||
"destination": "https://gse-frontend-preview.vercel.app/:match*"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
+16
-16
@@ -3,36 +3,36 @@ module.exports = {
|
||||
browser: true,
|
||||
es6: true,
|
||||
},
|
||||
extends: ['plugin:prettier/recommended'],
|
||||
extends: ["plugin:prettier/recommended"],
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
ecmaVersion: 2020,
|
||||
sourceType: 'module',
|
||||
sourceType: "module",
|
||||
},
|
||||
plugins: ['prettier'],
|
||||
plugins: ["prettier"],
|
||||
rules: {
|
||||
'react/jsx-filename-extension': 'off',
|
||||
'react/forbid-prop-types': 'off',
|
||||
'react/destructuring-assignment': 'off',
|
||||
'import/prefer-default-export': 'off',
|
||||
'react/function-component-definition': 'off',
|
||||
'react/no-unstable-nested-components': 'off',
|
||||
'no-console': 'off',
|
||||
radix: 'off',
|
||||
'prettier/prettier': [
|
||||
'error',
|
||||
"react/jsx-filename-extension": "off",
|
||||
"react/forbid-prop-types": "off",
|
||||
"react/destructuring-assignment": "off",
|
||||
"import/prefer-default-export": "off",
|
||||
"react/function-component-definition": "off",
|
||||
"react/no-unstable-nested-components": "off",
|
||||
"no-console": "off",
|
||||
radix: "off",
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
endOfLine: 'auto',
|
||||
endOfLine: "auto",
|
||||
},
|
||||
],
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['./src/backend/**/*'],
|
||||
files: ["./src/backend/**/*"],
|
||||
rules: {
|
||||
'prettier/prettier': 'off',
|
||||
"prettier/prettier": "off",
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
@@ -1,7 +0,0 @@
|
||||
module.exports = {
|
||||
semi: true,
|
||||
trailingComma: 'all',
|
||||
singleQuote: true,
|
||||
printWidth: 80,
|
||||
tabWidth: 2,
|
||||
};
|
||||
@@ -1,38 +1,39 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const path = require("path");
|
||||
const webpack = require("webpack");
|
||||
|
||||
module.exports = {
|
||||
webpack: {
|
||||
alias: {
|
||||
dotenv: path.resolve(__dirname, 'src/dotenv-browser-stub.js'),
|
||||
'../src/fetchers/wakatime.js': path.resolve(__dirname, 'src/wakatime-override.js'),
|
||||
dotenv: path.resolve(__dirname, "src/dotenv-browser-stub.js"),
|
||||
"../src/fetchers/wakatime.js": path.resolve(
|
||||
__dirname,
|
||||
"src/wakatime-override.js",
|
||||
),
|
||||
},
|
||||
|
||||
configure: (webpackConfig) => {
|
||||
webpackConfig.resolve.fallback = {
|
||||
...webpackConfig.resolve.fallback,
|
||||
pg: false,
|
||||
path: require.resolve('path-browserify'),
|
||||
querystring: require.resolve('querystring-es3'),
|
||||
url: require.resolve('url/'),
|
||||
http: require.resolve('stream-http'),
|
||||
util: require.resolve('util/'),
|
||||
stream: require.resolve('stream-browserify'),
|
||||
buffer: require.resolve('buffer/'),
|
||||
path: require.resolve("path-browserify"),
|
||||
querystring: require.resolve("querystring-es3"),
|
||||
url: require.resolve("url/"),
|
||||
http: require.resolve("stream-http"),
|
||||
util: require.resolve("util/"),
|
||||
stream: require.resolve("stream-browserify"),
|
||||
buffer: require.resolve("buffer/"),
|
||||
fs: false,
|
||||
net: false,
|
||||
};
|
||||
|
||||
// remove the DefinePlugin, which (only) replaces process.env in code
|
||||
webpackConfig.plugins = webpackConfig.plugins.filter(
|
||||
function (plugin) {
|
||||
let isDefinePlugin = plugin instanceof webpack.DefinePlugin;
|
||||
if (isDefinePlugin) {
|
||||
console.log("filtered plugin:", plugin);
|
||||
}
|
||||
return !isDefinePlugin;
|
||||
webpackConfig.plugins = webpackConfig.plugins.filter(function (plugin) {
|
||||
let isDefinePlugin = plugin instanceof webpack.DefinePlugin;
|
||||
if (isDefinePlugin) {
|
||||
console.log("filtered plugin:", plugin);
|
||||
}
|
||||
);
|
||||
return !isDefinePlugin;
|
||||
});
|
||||
|
||||
return webpackConfig;
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
@@ -13,7 +13,10 @@
|
||||
/>
|
||||
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://github-stats-extended.vercel.app/frontend" />
|
||||
<meta
|
||||
property="og:url"
|
||||
content="https://github-stats-extended.vercel.app/frontend"
|
||||
/>
|
||||
<meta property="og:title" content="GitHub Stats Extended" />
|
||||
<meta
|
||||
property="og:description"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import { authenticate, getUserMetadata, deleteAccount } from './user';
|
||||
import { authenticate, getUserMetadata, deleteAccount } from "./user";
|
||||
|
||||
export { authenticate, getUserMetadata, deleteAccount };
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import axios from 'axios';
|
||||
import axios from "axios";
|
||||
|
||||
import { HOST } from '../constants';
|
||||
import { HOST } from "../constants";
|
||||
|
||||
const authenticate = async (code, privateAccess, userKey) => {
|
||||
try {
|
||||
@@ -16,7 +16,7 @@ const authenticate = async (code, privateAccess, userKey) => {
|
||||
return userId;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return '';
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
@@ -38,7 +38,7 @@ const deleteAccount = async (userId, userKey) => {
|
||||
return result.data; // no decorator
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return '';
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
import axios, { getAdapter } from 'axios';
|
||||
import { setupCache } from 'axios-cache-interceptor';
|
||||
import { HOST } from './constants';
|
||||
import axios, { getAdapter } from "axios";
|
||||
import { setupCache } from "axios-cache-interceptor";
|
||||
import { HOST } from "./constants";
|
||||
|
||||
import additionalUserStars from './mockData/additional_user_stars.json' with { type: 'json' };
|
||||
import commentedIssues from './mockData/commented_issues.json' with { type: 'json' };
|
||||
import commentedPrs from './mockData/commented_prs.json' with { type: 'json' };
|
||||
import commits from './mockData/commits.json' with { type: 'json' };
|
||||
import gist_graphql from './mockData/gist-graphql.json' with { type: 'json' };
|
||||
import gist_rest from './mockData/gist-rest.json' with { type: 'json' };
|
||||
import repository from './mockData/repository.json' with { type: 'json' };
|
||||
import reviewedPrs from './mockData/reviewed_prs.json' with { type: 'json' };
|
||||
import topLanguages from './mockData/top_languages.json' with { type: 'json' };
|
||||
import userStats from './mockData/user_stats.json' with { type: 'json' };
|
||||
import wakatimeProxy from './mockData/wakatime_proxy.json' with { type: 'json' };
|
||||
import additionalUserStars from "./mockData/additional_user_stars.json" with { type: "json" };
|
||||
import commentedIssues from "./mockData/commented_issues.json" with { type: "json" };
|
||||
import commentedPrs from "./mockData/commented_prs.json" with { type: "json" };
|
||||
import commits from "./mockData/commits.json" with { type: "json" };
|
||||
import gist_graphql from "./mockData/gist-graphql.json" with { type: "json" };
|
||||
import gist_rest from "./mockData/gist-rest.json" with { type: "json" };
|
||||
import repository from "./mockData/repository.json" with { type: "json" };
|
||||
import reviewedPrs from "./mockData/reviewed_prs.json" with { type: "json" };
|
||||
import topLanguages from "./mockData/top_languages.json" with { type: "json" };
|
||||
import userStats from "./mockData/user_stats.json" with { type: "json" };
|
||||
import wakatimeProxy from "./mockData/wakatime_proxy.json" with { type: "json" };
|
||||
|
||||
const cachedAxios = setupCache(axios, {
|
||||
// Cache for 30 minutes
|
||||
ttl: 30 * 60 * 1000,
|
||||
interpretHeader: false,
|
||||
cacheTakeover: false,
|
||||
methods: ['get', 'post'],
|
||||
methods: ["get", "post"],
|
||||
cachePredicate: {
|
||||
allowUrls: ['api.github.com', HOST],
|
||||
allowUrls: ["api.github.com", HOST],
|
||||
},
|
||||
});
|
||||
|
||||
@@ -36,7 +36,7 @@ function createMockResponse(data, config) {
|
||||
return Promise.resolve({
|
||||
data,
|
||||
status: 200,
|
||||
statusText: 'OK',
|
||||
statusText: "OK",
|
||||
headers: {},
|
||||
request: {},
|
||||
config,
|
||||
@@ -61,62 +61,62 @@ axios.defaults.adapter = async (config) => {
|
||||
const params = config.data ? JSON.parse(config.data) : {};
|
||||
|
||||
if (
|
||||
config.url === 'https://api.github.com/graphql' &&
|
||||
config.url === "https://api.github.com/graphql" &&
|
||||
params.query?.includes(
|
||||
'query userInfo($login: String!, $after: String, $includeMergedPullRequests:',
|
||||
"query userInfo($login: String!, $after: String, $includeMergedPullRequests:",
|
||||
) &&
|
||||
params.variables?.login === 'anuraghazra'
|
||||
params.variables?.login === "anuraghazra"
|
||||
) {
|
||||
return createMockResponse(userStats, config);
|
||||
}
|
||||
|
||||
if (
|
||||
config.url === 'https://api.github.com/graphql' &&
|
||||
config.url === "https://api.github.com/graphql" &&
|
||||
params.query?.includes(
|
||||
'query userInfo($login: String!, $after: String, $ownerAffiliations:',
|
||||
"query userInfo($login: String!, $after: String, $ownerAffiliations:",
|
||||
) &&
|
||||
params.variables?.login === 'anuraghazra'
|
||||
params.variables?.login === "anuraghazra"
|
||||
) {
|
||||
return createMockResponse(additionalUserStars, config);
|
||||
}
|
||||
|
||||
if (
|
||||
config.url === 'https://api.github.com/graphql' &&
|
||||
config.url === "https://api.github.com/graphql" &&
|
||||
params.query?.includes(
|
||||
'query userInfo($login: String!, $ownerAffiliations:',
|
||||
"query userInfo($login: String!, $ownerAffiliations:",
|
||||
) &&
|
||||
params.variables?.login === 'anuraghazra'
|
||||
params.variables?.login === "anuraghazra"
|
||||
) {
|
||||
return createMockResponse(topLanguages, config);
|
||||
}
|
||||
|
||||
if (
|
||||
config.url === 'https://api.github.com/graphql' &&
|
||||
params.query?.includes('fragment RepoInfo on Repository {') &&
|
||||
params.variables?.login === 'anuraghazra' &&
|
||||
params.variables?.repo === 'github-readme-stats'
|
||||
config.url === "https://api.github.com/graphql" &&
|
||||
params.query?.includes("fragment RepoInfo on Repository {") &&
|
||||
params.variables?.login === "anuraghazra" &&
|
||||
params.variables?.repo === "github-readme-stats"
|
||||
) {
|
||||
return createMockResponse(repository, config);
|
||||
}
|
||||
|
||||
if (
|
||||
config.url === 'https://api.github.com/graphql' &&
|
||||
params.query?.includes('query gistInfo(') &&
|
||||
params.variables?.gistName === 'bbfce31e0217a3689c8d961a356cb10d'
|
||||
config.url === "https://api.github.com/graphql" &&
|
||||
params.query?.includes("query gistInfo(") &&
|
||||
params.variables?.gistName === "bbfce31e0217a3689c8d961a356cb10d"
|
||||
) {
|
||||
return createMockResponse(gist_graphql, config);
|
||||
}
|
||||
|
||||
switch (config.url) {
|
||||
case 'https://api.github.com/gists/bbfce31e0217a3689c8d961a356cb10d':
|
||||
case "https://api.github.com/gists/bbfce31e0217a3689c8d961a356cb10d":
|
||||
return createMockResponse(gist_rest, config);
|
||||
case 'https://api.github.com/search/commits?per_page=1&q=author:anuraghazra':
|
||||
case "https://api.github.com/search/commits?per_page=1&q=author:anuraghazra":
|
||||
return createMockResponse(commits, config);
|
||||
case 'https://api.github.com/search/issues?per_page=1&q=commenter:anuraghazra+-author:anuraghazra+type:pr':
|
||||
case "https://api.github.com/search/issues?per_page=1&q=commenter:anuraghazra+-author:anuraghazra+type:pr":
|
||||
return createMockResponse(commentedPrs, config);
|
||||
case 'https://api.github.com/search/issues?per_page=1&q=reviewed-by:anuraghazra+-author:anuraghazra+type:pr':
|
||||
case "https://api.github.com/search/issues?per_page=1&q=reviewed-by:anuraghazra+-author:anuraghazra+type:pr":
|
||||
return createMockResponse(reviewedPrs, config);
|
||||
case 'https://api.github.com/search/issues?per_page=1&q=commenter:anuraghazra+-author:anuraghazra+type:issue':
|
||||
case "https://api.github.com/search/issues?per_page=1&q=commenter:anuraghazra+-author:anuraghazra+type:issue":
|
||||
return createMockResponse(commentedIssues, config);
|
||||
case `https://${HOST}/api/wakatime-proxy?username=ffflabs`:
|
||||
return createMockResponse(wakatimeProxy, config);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import SVG from './SVG';
|
||||
import { classnames } from '../../utils';
|
||||
import { HOST } from '../../constants';
|
||||
import SVG from "./SVG";
|
||||
import { classnames } from "../../utils";
|
||||
import { HOST } from "../../constants";
|
||||
|
||||
export const Image = ({ imageSrc, stage, compact, extraClasses = '' }) => {
|
||||
export const Image = ({ imageSrc, stage, compact, extraClasses = "" }) => {
|
||||
const fullImageSrc = `https://${HOST}/api${imageSrc}&client=wizard`;
|
||||
|
||||
return (
|
||||
@@ -29,7 +29,7 @@ Image.propTypes = {
|
||||
|
||||
Image.defaultProps = {
|
||||
compact: false,
|
||||
extraClasses: '',
|
||||
extraClasses: "",
|
||||
};
|
||||
|
||||
export const Card = ({
|
||||
@@ -44,11 +44,11 @@ export const Card = ({
|
||||
return (
|
||||
<div
|
||||
className={classnames(
|
||||
'p-6 rounded border-2',
|
||||
fixedSize ? 'h-[370px] w-[510px]' : '',
|
||||
"p-6 rounded border-2",
|
||||
fixedSize ? "h-[370px] w-[510px]" : "",
|
||||
selected
|
||||
? 'border-blue-500 bg-blue-50'
|
||||
: 'border-gray-200 bg-white hover:bg-gray-50',
|
||||
? "border-blue-500 bg-blue-50"
|
||||
: "border-gray-200 bg-white hover:bg-gray-50",
|
||||
)}
|
||||
>
|
||||
<h2 className="text-xl font-medium title-font text-gray-900">{title}</h2>
|
||||
@@ -56,7 +56,7 @@ export const Card = ({
|
||||
<Image
|
||||
imageSrc={imageSrc}
|
||||
compact={compact}
|
||||
extraClasses={fixedSize ? 'flex justify-center' : ''}
|
||||
extraClasses={fixedSize ? "flex justify-center" : ""}
|
||||
stage={stage}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/* eslint-disable react/jsx-props-no-spreading */
|
||||
/* eslint-disable react/no-danger */
|
||||
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Skeleton from 'react-loading-skeleton';
|
||||
import 'react-loading-skeleton/dist/skeleton.css';
|
||||
import Skeleton from "react-loading-skeleton";
|
||||
import "react-loading-skeleton/dist/skeleton.css";
|
||||
|
||||
import { createMockReq, createMockRes } from '../../mock-http';
|
||||
import { default as router } from '../../backend/.vercel/output/functions/api.func/router.js';
|
||||
import { setShouldMock } from '../../axios-override';
|
||||
import { createMockReq, createMockRes } from "../../mock-http";
|
||||
import { default as router } from "../../backend/.vercel/output/functions/api.func/router.js";
|
||||
import { setShouldMock } from "../../axios-override";
|
||||
import {
|
||||
useIsAuthenticated,
|
||||
useUserToken,
|
||||
} from '../../redux/selectors/userSelectors';
|
||||
import axios from 'axios';
|
||||
} from "../../redux/selectors/userSelectors";
|
||||
import axios from "axios";
|
||||
|
||||
const SvgInline = (props) => {
|
||||
const [svg, setSvg] = useState(null);
|
||||
@@ -40,7 +40,7 @@ const SvgInline = (props) => {
|
||||
let body;
|
||||
let status;
|
||||
|
||||
if (isAuthenticated && (!userToken || userToken === 'placeholderPAT')) {
|
||||
if (isAuthenticated && (!userToken || userToken === "placeholderPAT")) {
|
||||
// waiting for backend call to private-access
|
||||
return;
|
||||
}
|
||||
@@ -51,7 +51,7 @@ const SvgInline = (props) => {
|
||||
status = res.status;
|
||||
} else {
|
||||
const req = createMockReq({
|
||||
method: 'GET',
|
||||
method: "GET",
|
||||
url: url,
|
||||
});
|
||||
const res = createMockRes();
|
||||
@@ -61,7 +61,7 @@ const SvgInline = (props) => {
|
||||
}
|
||||
|
||||
if (status >= 300) {
|
||||
console.error('failed to fetch/generate SVG');
|
||||
console.error("failed to fetch/generate SVG");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -83,12 +83,12 @@ const SvgInline = (props) => {
|
||||
// Attach shadow root if not already present
|
||||
let shadow = containerRef.current.shadowRoot;
|
||||
if (!shadow) {
|
||||
shadow = containerRef.current.attachShadow({ mode: 'open' });
|
||||
shadow = containerRef.current.attachShadow({ mode: "open" });
|
||||
}
|
||||
// Clear previous content
|
||||
shadow.innerHTML = '';
|
||||
shadow.innerHTML = "";
|
||||
// Insert SVG
|
||||
const wrapper = document.createElement('div');
|
||||
const wrapper = document.createElement("div");
|
||||
wrapper.innerHTML = svg;
|
||||
shadow.appendChild(wrapper);
|
||||
}
|
||||
@@ -96,7 +96,7 @@ const SvgInline = (props) => {
|
||||
|
||||
if (props.forceLoading || !loaded) {
|
||||
if (props.compact) {
|
||||
return <Skeleton style={{ paddingBottom: '58%' }} />;
|
||||
return <Skeleton style={{ paddingBottom: "58%" }} />;
|
||||
}
|
||||
// maximum dimensions of cards in SelectCard stage
|
||||
return <Skeleton className="h-[245px] w-[450px]" />;
|
||||
@@ -115,7 +115,7 @@ SvgInline.propTypes = {
|
||||
};
|
||||
|
||||
SvgInline.defaultProps = {
|
||||
className: '',
|
||||
className: "",
|
||||
forceLoading: false,
|
||||
compact: false,
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import SvgInline from './SVG';
|
||||
import { Card, Image } from './Card';
|
||||
import SvgInline from "./SVG";
|
||||
import { Card, Image } from "./Card";
|
||||
|
||||
export { Card, Image, SvgInline };
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* eslint-disable react/jsx-props-no-spreading */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { classnames } from '../../utils';
|
||||
import { classnames } from "../../utils";
|
||||
|
||||
const Button = (props) => {
|
||||
return (
|
||||
@@ -11,7 +11,7 @@ const Button = (props) => {
|
||||
{...props}
|
||||
className={classnames(
|
||||
props.className,
|
||||
'border-0 py-2 px-6 inline-flex focus:outline-none rounded-[0.25rem] text-lg',
|
||||
"border-0 py-2 px-6 inline-flex focus:outline-none rounded-[0.25rem] text-lg",
|
||||
)}
|
||||
>
|
||||
{props.children}
|
||||
@@ -25,7 +25,7 @@ Button.propTypes = {
|
||||
};
|
||||
|
||||
Button.defaultProps = {
|
||||
className: '',
|
||||
className: "",
|
||||
};
|
||||
|
||||
export default Button;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
const Checkbox = ({ question, variable, setVariable, disabled }) => {
|
||||
return (
|
||||
@@ -11,7 +11,7 @@ const Checkbox = ({ question, variable, setVariable, disabled }) => {
|
||||
<input
|
||||
type="checkbox"
|
||||
disabled={disabled}
|
||||
checked={variable && !disabled ? 'checked' : ''}
|
||||
checked={variable && !disabled ? "checked" : ""}
|
||||
className="checkbox mr-2"
|
||||
onChange={() => setVariable(!variable)}
|
||||
/>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { classnames } from '../../utils';
|
||||
import { classnames } from "../../utils";
|
||||
|
||||
// options is of form [{value: '', label: '', disabled: true/false}]
|
||||
const Input = ({
|
||||
@@ -14,15 +14,15 @@ const Input = ({
|
||||
return (
|
||||
<select
|
||||
className={classnames(
|
||||
'text-gray-700 bg-white select select-sm w-40 rounded-sm mt-4',
|
||||
"text-gray-700 bg-white select select-sm w-40 rounded-sm mt-4",
|
||||
className,
|
||||
)}
|
||||
value={selectedOption.label}
|
||||
onChange={(e) =>
|
||||
onChange={(e) => {
|
||||
setSelectedOption(
|
||||
options.find((item) => item.label === e.target.value),
|
||||
// eslint-disable-next-line prettier/prettier
|
||||
)}
|
||||
);
|
||||
}}
|
||||
disabled={disabled}
|
||||
>
|
||||
{options.map((option) => (
|
||||
@@ -30,7 +30,7 @@ const Input = ({
|
||||
key={option.value}
|
||||
disabled={option.disabled}
|
||||
className={classnames(
|
||||
option.label === selectedOption.label && 'bg-blue-200',
|
||||
option.label === selectedOption.label && "bg-blue-200",
|
||||
)}
|
||||
>
|
||||
{option.label}
|
||||
@@ -59,7 +59,7 @@ Input.propTypes = {
|
||||
|
||||
Input.defaultProps = {
|
||||
disabled: false,
|
||||
className: '',
|
||||
className: "",
|
||||
};
|
||||
|
||||
export default Input;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Button from './Button';
|
||||
import Checkbox from './Checkbox';
|
||||
import Input from './Input';
|
||||
import Button from "./Button";
|
||||
import Checkbox from "./Checkbox";
|
||||
import Input from "./Input";
|
||||
|
||||
export { Button, Checkbox, Input };
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* eslint-disable react/no-danger */
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Section from './Section';
|
||||
import { Checkbox } from '../Generic';
|
||||
import Section from "./Section";
|
||||
import { Checkbox } from "../Generic";
|
||||
|
||||
const CheckboxSection = ({
|
||||
title,
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Section from './Section';
|
||||
import { Input } from '../Generic';
|
||||
import Section from "./Section";
|
||||
import { Input } from "../Generic";
|
||||
|
||||
export const DEFAULT_OPTION = {
|
||||
id: 1,
|
||||
label: 'Normal',
|
||||
label: "Normal",
|
||||
disabled: false,
|
||||
value: 'normal',
|
||||
value: "normal",
|
||||
};
|
||||
|
||||
const LanguagesLayoutSection = ({ selectedOption, setSelectedOption }) => {
|
||||
const options = [
|
||||
DEFAULT_OPTION,
|
||||
{ id: 2, label: 'Compact', disabled: false, value: 'compact' },
|
||||
{ id: 3, label: 'Donut', disabled: false, value: 'donut' },
|
||||
{ id: 2, label: "Compact", disabled: false, value: "compact" },
|
||||
{ id: 3, label: "Donut", disabled: false, value: "donut" },
|
||||
{
|
||||
id: 4,
|
||||
label: 'Vertical Donut',
|
||||
label: "Vertical Donut",
|
||||
disabled: false,
|
||||
value: 'donut-vertical',
|
||||
value: "donut-vertical",
|
||||
},
|
||||
{ id: 5, label: 'Pie', disabled: false, value: 'pie' },
|
||||
{ id: 5, label: "Pie", disabled: false, value: "pie" },
|
||||
{
|
||||
id: 6,
|
||||
label: 'Only Languages',
|
||||
label: "Only Languages",
|
||||
disabled: false,
|
||||
value: 'compact&hide_progress=true',
|
||||
value: "compact&hide_progress=true",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* eslint-disable react/no-danger */
|
||||
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Section from './Section';
|
||||
import Section from "./Section";
|
||||
|
||||
const NumericSection = ({
|
||||
title,
|
||||
@@ -73,7 +73,7 @@ NumericSection.defaultProps = {
|
||||
max: undefined,
|
||||
step: 1,
|
||||
disabled: false,
|
||||
placeholder: '',
|
||||
placeholder: "",
|
||||
};
|
||||
|
||||
export default NumericSection;
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
/* eslint-disable react/no-array-index-key */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import {
|
||||
FaArrowLeft as LeftArrowIcon,
|
||||
FaArrowRight as RightArrowIcon,
|
||||
} from 'react-icons/fa';
|
||||
} from "react-icons/fa";
|
||||
|
||||
import { classnames } from '../../utils';
|
||||
import { classnames } from "../../utils";
|
||||
|
||||
const ProgressSection = ({ num, item, passed, isActive, onClick }) => {
|
||||
return (
|
||||
<button
|
||||
className={classnames(
|
||||
'w-1/4 flex flex-col mx-2 p-2 cursor-pointer',
|
||||
passed ? 'border-blue-500' : 'border-gray-500',
|
||||
isActive ? 'border-t-[14px] -mt-[5px]' : 'border-t-4',
|
||||
"w-1/4 flex flex-col mx-2 p-2 cursor-pointer",
|
||||
passed ? "border-blue-500" : "border-gray-500",
|
||||
isActive ? "border-t-[14px] -mt-[5px]" : "border-t-4",
|
||||
)}
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
>
|
||||
<div
|
||||
className={classnames(
|
||||
'text-lg font-bold',
|
||||
passed ? 'text-blue-500' : 'text-gray-500',
|
||||
isActive ? '-mt-[4px]' : '',
|
||||
"text-lg font-bold",
|
||||
passed ? "text-blue-500" : "text-gray-500",
|
||||
isActive ? "-mt-[4px]" : "",
|
||||
)}
|
||||
>
|
||||
{`Step ${num + 1}`}
|
||||
</div>
|
||||
<div className={classnames(passed ? 'text-gray-700' : 'text-gray-500')}>
|
||||
<div className={classnames(passed ? "text-gray-700" : "text-gray-500")}>
|
||||
{item}
|
||||
</div>
|
||||
</button>
|
||||
@@ -52,10 +52,10 @@ const ProgressBar = ({ items, currItem, setCurrItem }) => {
|
||||
<div className="w-full flex items-center sticky top-0 bg-gray-200 z-50 pt-3 pb-1 px-1 md:px-20 shadow-md">
|
||||
<LeftArrowIcon
|
||||
className={classnames(
|
||||
'w-8 h-8',
|
||||
"w-8 h-8",
|
||||
leftDisabled
|
||||
? 'text-gray-400 cursor-not-allowed'
|
||||
: 'text-gray-700 cursor-pointer',
|
||||
? "text-gray-400 cursor-not-allowed"
|
||||
: "text-gray-700 cursor-pointer",
|
||||
)}
|
||||
onClick={() => setCurrItem(Math.max(currItem - 1, 0))}
|
||||
/>
|
||||
@@ -75,10 +75,10 @@ const ProgressBar = ({ items, currItem, setCurrItem }) => {
|
||||
</div>
|
||||
<RightArrowIcon
|
||||
className={classnames(
|
||||
'w-8 h-8',
|
||||
"w-8 h-8",
|
||||
rightDisabled
|
||||
? 'text-gray-400 cursor-not-allowed'
|
||||
: 'text-gray-700 cursor-pointer',
|
||||
? "text-gray-400 cursor-not-allowed"
|
||||
: "text-gray-700 cursor-pointer",
|
||||
)}
|
||||
onClick={() => setCurrItem(Math.min(currItem + 1, items.length - 1))}
|
||||
/>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { HiOutlineLightningBolt as LightningIcon } from 'react-icons/hi';
|
||||
import { HiOutlineLightningBolt as LightningIcon } from "react-icons/hi";
|
||||
|
||||
const Section = (props) => {
|
||||
return (
|
||||
@@ -29,7 +29,7 @@ Section.propTypes = {
|
||||
};
|
||||
|
||||
Section.defaultProps = {
|
||||
title: 'Test',
|
||||
title: "Test",
|
||||
children: <p className="leading-relaxed">This is a test!</p>,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Section from './Section';
|
||||
import { Input } from '../Generic';
|
||||
import Section from "./Section";
|
||||
import { Input } from "../Generic";
|
||||
|
||||
export const DEFAULT_OPTION = {
|
||||
id: 1,
|
||||
label: 'Rank',
|
||||
label: "Rank",
|
||||
disabled: false,
|
||||
value: 'default',
|
||||
value: "default",
|
||||
};
|
||||
|
||||
const StatsRankSection = ({ selectedOption, setSelectedOption }) => {
|
||||
const options = [
|
||||
DEFAULT_OPTION,
|
||||
{ id: 2, label: 'Percentile', disabled: false, value: 'percentile' },
|
||||
{ id: 3, label: 'GitHub', disabled: false, value: 'github' },
|
||||
{ id: 4, label: 'None', disabled: false, value: 'default&hide_rank=true' },
|
||||
{ id: 2, label: "Percentile", disabled: false, value: "percentile" },
|
||||
{ id: 3, label: "GitHub", disabled: false, value: "github" },
|
||||
{ id: 4, label: "None", disabled: false, value: "default&hide_rank=true" },
|
||||
];
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* eslint-disable react/no-danger */
|
||||
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Section from './Section';
|
||||
import { classnames } from '../../utils';
|
||||
import Section from "./Section";
|
||||
import { classnames } from "../../utils";
|
||||
|
||||
const TextSection = ({
|
||||
title,
|
||||
@@ -43,8 +43,8 @@ const TextSection = ({
|
||||
<input
|
||||
type="text"
|
||||
className={classnames(
|
||||
'border border-gray-300 rounded px-2 py-1 mt-2 w-3/4 min-w-48 max-w-xl',
|
||||
disabled ? 'cursor-not-allowed' : '',
|
||||
"border border-gray-300 rounded px-2 py-1 mt-2 w-3/4 min-w-48 max-w-xl",
|
||||
disabled ? "cursor-not-allowed" : "",
|
||||
)}
|
||||
value={internalValue}
|
||||
onChange={(e) => setInternalValue(e.target.value)}
|
||||
@@ -68,7 +68,7 @@ TextSection.propTypes = {
|
||||
|
||||
TextSection.defaultProps = {
|
||||
disabled: false,
|
||||
placeholder: '',
|
||||
placeholder: "",
|
||||
onPaste: undefined,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Section from './Section';
|
||||
import { Input } from '../Generic';
|
||||
import Section from "./Section";
|
||||
import { Input } from "../Generic";
|
||||
|
||||
export const DEFAULT_OPTION = {
|
||||
id: 1,
|
||||
label: 'Normal',
|
||||
label: "Normal",
|
||||
disabled: false,
|
||||
value: 'default',
|
||||
value: "default",
|
||||
};
|
||||
|
||||
const WakatimeLayoutSection = ({ selectedOption, setSelectedOption }) => {
|
||||
const options = [
|
||||
DEFAULT_OPTION,
|
||||
{ id: 2, label: 'Compact', disabled: false, value: 'compact' },
|
||||
{ id: 2, label: "Compact", disabled: false, value: "compact" },
|
||||
{
|
||||
id: 3,
|
||||
label: 'Text Only',
|
||||
label: "Text Only",
|
||||
disabled: false,
|
||||
value: 'default&hide_progress=true&card_width=315',
|
||||
value: "default&hide_progress=true&card_width=315",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ProgressBar from './Progress';
|
||||
import CheckboxSection from './CheckboxSection';
|
||||
import ProgressBar from "./Progress";
|
||||
import CheckboxSection from "./CheckboxSection";
|
||||
|
||||
export { ProgressBar, CheckboxSection };
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { useState, useEffect } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import {
|
||||
FaArrowRight as ArrowRightIcon,
|
||||
FaArrowLeft as ArrowLeftIcon,
|
||||
} from 'react-icons/fa';
|
||||
} from "react-icons/fa";
|
||||
|
||||
import { classnames } from '../../utils';
|
||||
import { classnames } from "../../utils";
|
||||
|
||||
const Preview = ({ pages, details, showArrows }) => {
|
||||
const totalPages = pages.length;
|
||||
@@ -38,7 +38,7 @@ const Preview = ({ pages, details, showArrows }) => {
|
||||
<img
|
||||
src={pages[page]}
|
||||
alt="preview"
|
||||
className={showArrows ? 'w-3/4 mx-auto' : 'w-full'}
|
||||
className={showArrows ? "w-3/4 mx-auto" : "w-full"}
|
||||
/>
|
||||
{showArrows && (
|
||||
<ArrowRightIcon
|
||||
@@ -50,8 +50,8 @@ const Preview = ({ pages, details, showArrows }) => {
|
||||
<br />
|
||||
<p
|
||||
className={classnames(
|
||||
'w-full text-center',
|
||||
'text-sm lg:text-lg xl:text-xl 2xl:text-2xl',
|
||||
"w-full text-center",
|
||||
"text-sm lg:text-lg xl:text-xl 2xl:text-2xl",
|
||||
)}
|
||||
>
|
||||
{details[page]}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import Preview from './Preview';
|
||||
import Preview from "./Preview";
|
||||
|
||||
export default Preview;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Preview from './Preview';
|
||||
import Preview from "./Preview";
|
||||
|
||||
export * from './Generic';
|
||||
export * from './Card';
|
||||
export * from './Home';
|
||||
export * from "./Generic";
|
||||
export * from "./Card";
|
||||
export * from "./Home";
|
||||
|
||||
export { Preview };
|
||||
|
||||
@@ -3,25 +3,25 @@ export const PROD = false;
|
||||
|
||||
export const USE_LOGGER = true;
|
||||
|
||||
export const CLIENT_ID = 'Ov23lilAc5biyyRY0K1u';
|
||||
export const CLIENT_ID = "Ov23lilAc5biyyRY0K1u";
|
||||
|
||||
export const HOST = PROD
|
||||
? 'github-stats-extended.vercel.app'
|
||||
: 'github-stats-extended-preview.vercel.app';
|
||||
? "github-stats-extended.vercel.app"
|
||||
: "github-stats-extended-preview.vercel.app";
|
||||
|
||||
export const REDIRECT_URI = `https://${HOST}/frontend`;
|
||||
|
||||
export const GITHUB_PRIVATE_AUTH_URL = `https://github.com/login/oauth/authorize?scope=user,repo&client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}/private`;
|
||||
export const GITHUB_PUBLIC_AUTH_URL = `https://github.com/login/oauth/authorize?client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}/public`;
|
||||
|
||||
export const DEMO_USER = 'anuraghazra';
|
||||
export const DEMO_REPO = 'anuraghazra/github-readme-stats';
|
||||
export const DEMO_GIST = 'bbfce31e0217a3689c8d961a356cb10d';
|
||||
export const DEMO_WAKATIME_USER = 'ffflabs';
|
||||
export const DEMO_USER = "anuraghazra";
|
||||
export const DEMO_REPO = "anuraghazra/github-readme-stats";
|
||||
export const DEMO_GIST = "bbfce31e0217a3689c8d961a356cb10d";
|
||||
export const DEMO_WAKATIME_USER = "ffflabs";
|
||||
|
||||
window.process = {
|
||||
env: {
|
||||
FETCH_MULTI_PAGE_STARS: 10,
|
||||
PAT_1: 'placeholderPAT', // so the backend's retryer.js sees there is 1 PAT and sets `RETRIES` accordingly
|
||||
PAT_1: "placeholderPAT", // so the backend's retryer.js sees there is 1 PAT and sets `RETRIES` accordingly
|
||||
},
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Segoe UI', Ubuntu, Sans-Serif;
|
||||
font-family: "Segoe UI", Ubuntu, Sans-Serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import './axios-override';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import { Provider } from 'react-redux';
|
||||
import "./axios-override";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import { Provider } from "react-redux";
|
||||
|
||||
import configureStore from './redux/store';
|
||||
import { AppTrends } from './pages/App';
|
||||
import './index.css';
|
||||
import configureStore from "./redux/store";
|
||||
import { AppTrends } from "./pages/App";
|
||||
import "./index.css";
|
||||
|
||||
export const store = configureStore();
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
const root = ReactDOM.createRoot(document.getElementById("root"));
|
||||
|
||||
root.render(
|
||||
<Provider store={store}>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export function createMockReq({
|
||||
method = 'GET',
|
||||
method = "GET",
|
||||
url,
|
||||
headers = {},
|
||||
body = null,
|
||||
@@ -32,7 +32,7 @@ export function createMockRes() {
|
||||
},
|
||||
|
||||
write(chunk) {
|
||||
if (typeof chunk !== 'string') {
|
||||
if (typeof chunk !== "string") {
|
||||
chunk = String(chunk);
|
||||
}
|
||||
chunks.push(chunk);
|
||||
@@ -50,7 +50,7 @@ export function createMockRes() {
|
||||
return { ...headers };
|
||||
},
|
||||
_getBody() {
|
||||
return chunks.join('');
|
||||
return chunks.join("");
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -34,9 +34,7 @@
|
||||
"user_view_type": "public",
|
||||
"site_admin": false
|
||||
},
|
||||
"labels": [
|
||||
|
||||
],
|
||||
"labels": [],
|
||||
"state": "closed",
|
||||
"locked": false,
|
||||
"assignee": {
|
||||
|
||||
@@ -34,15 +34,11 @@
|
||||
"user_view_type": "public",
|
||||
"site_admin": false
|
||||
},
|
||||
"labels": [
|
||||
|
||||
],
|
||||
"labels": [],
|
||||
"state": "open",
|
||||
"locked": false,
|
||||
"assignee": null,
|
||||
"assignees": [
|
||||
|
||||
],
|
||||
"assignees": [],
|
||||
"milestone": null,
|
||||
"comments": 2,
|
||||
"created_at": "2025-11-18T09:48:46Z",
|
||||
|
||||
@@ -24,9 +24,7 @@
|
||||
"errors": [
|
||||
{
|
||||
"type": "NOT_FOUND",
|
||||
"path": [
|
||||
"organization"
|
||||
],
|
||||
"path": ["organization"],
|
||||
"locations": [
|
||||
{
|
||||
"line": 25,
|
||||
|
||||
@@ -34,15 +34,11 @@
|
||||
"user_view_type": "public",
|
||||
"site_admin": false
|
||||
},
|
||||
"labels": [
|
||||
|
||||
],
|
||||
"labels": [],
|
||||
"state": "open",
|
||||
"locked": false,
|
||||
"assignee": null,
|
||||
"assignees": [
|
||||
|
||||
],
|
||||
"assignees": [],
|
||||
"milestone": null,
|
||||
"comments": 2,
|
||||
"created_at": "2025-11-18T09:48:46Z",
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import { BrowserRouter as Router } from "react-router-dom";
|
||||
import {
|
||||
logout as _logout,
|
||||
setUserAccess as _setUserAccess,
|
||||
} from '../../redux/actions/userActions';
|
||||
} from "../../redux/actions/userActions";
|
||||
|
||||
import Header from './Header';
|
||||
import HomeScreen from '../Home';
|
||||
import { getUserMetadata } from '../../api';
|
||||
import Header from "./Header";
|
||||
import HomeScreen from "../Home";
|
||||
import { getUserMetadata } from "../../api";
|
||||
import {
|
||||
useIsAuthenticated,
|
||||
useUserKey,
|
||||
useUserToken,
|
||||
} from '../../redux/selectors/userSelectors';
|
||||
import { toast, ToastContainer } from 'react-toastify';
|
||||
import 'react-toastify/dist/ReactToastify.css';
|
||||
import { clearAxiosCache } from '../../axios-override';
|
||||
} from "../../redux/selectors/userSelectors";
|
||||
import { toast, ToastContainer } from "react-toastify";
|
||||
import "react-toastify/dist/ReactToastify.css";
|
||||
import { clearAxiosCache } from "../../axios-override";
|
||||
|
||||
function App() {
|
||||
const toMessage = (input) => {
|
||||
if (typeof input === 'string') return input;
|
||||
if (typeof input === "string") return input;
|
||||
if (input.reason?.message) return input.reason.message;
|
||||
if (input.message) return input.message;
|
||||
try {
|
||||
return JSON.stringify(input);
|
||||
} catch {
|
||||
return 'Unknown error';
|
||||
return "Unknown error";
|
||||
}
|
||||
};
|
||||
|
||||
const showError = (event) => {
|
||||
toast.error(toMessage(event), {
|
||||
position: 'bottom-right',
|
||||
position: "bottom-right",
|
||||
autoClose: 1500,
|
||||
hideProgressBar: true,
|
||||
closeOnClick: false,
|
||||
@@ -43,10 +43,10 @@ function App() {
|
||||
});
|
||||
};
|
||||
|
||||
window.addEventListener('error', (event) => {
|
||||
window.addEventListener("error", (event) => {
|
||||
showError(event);
|
||||
});
|
||||
window.addEventListener('unhandledrejection', (event) => {
|
||||
window.addEventListener("unhandledrejection", (event) => {
|
||||
showError(event);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
import appIcon from '../../assets/appLogo64.png';
|
||||
import { classnames } from '../../utils';
|
||||
import { FaGithub as GithubIcon } from 'react-icons/fa';
|
||||
import { ProgressBar } from '../../components';
|
||||
import appIcon from "../../assets/appLogo64.png";
|
||||
import { classnames } from "../../utils";
|
||||
import { FaGithub as GithubIcon } from "react-icons/fa";
|
||||
import { ProgressBar } from "../../components";
|
||||
|
||||
const propTypes = {
|
||||
to: PropTypes.string.isRequired,
|
||||
@@ -25,7 +25,7 @@ const StandardLink = ({ to, children, onClick, className }) => (
|
||||
<Link
|
||||
to={to}
|
||||
className={classnames(
|
||||
'px-4 py-1 mr-3 rounded-sm bg-gray-200 hover:bg-gray-300 text-gray-700',
|
||||
"px-4 py-1 mr-3 rounded-sm bg-gray-200 hover:bg-gray-300 text-gray-700",
|
||||
className,
|
||||
)}
|
||||
onClick={onClick}
|
||||
@@ -42,7 +42,7 @@ const MobileLink = ({ to, children, onClick, className }) => (
|
||||
<Link
|
||||
to={to}
|
||||
className={classnames(
|
||||
'block text-sm px-2 my-2 py-2 rounded-sm bg-gray-200 text-gray-700',
|
||||
"block text-sm px-2 my-2 py-2 rounded-sm bg-gray-200 text-gray-700",
|
||||
className,
|
||||
)}
|
||||
onClick={onClick}
|
||||
@@ -90,11 +90,11 @@ const Header = ({ stage, setStage }) => {
|
||||
</div>
|
||||
<ProgressBar
|
||||
items={[
|
||||
'Login',
|
||||
'Select Card',
|
||||
'Modify Parameters',
|
||||
'Select Theme',
|
||||
'Display Card',
|
||||
"Login",
|
||||
"Select Card",
|
||||
"Modify Parameters",
|
||||
"Select Theme",
|
||||
"Display Card",
|
||||
]}
|
||||
currItem={stage}
|
||||
setCurrItem={setStage}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import AppTrends from './AppTrends';
|
||||
import AppTrends from "./AppTrends";
|
||||
|
||||
export { AppTrends };
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import BounceLoader from 'react-spinners/BounceLoader';
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
import BounceLoader from "react-spinners/BounceLoader";
|
||||
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import {
|
||||
CustomizeStage,
|
||||
DisplayStage,
|
||||
LoginStage,
|
||||
SelectCardStage,
|
||||
ThemeStage,
|
||||
} from './stages';
|
||||
} from "./stages";
|
||||
|
||||
import { authenticate } from '../../api';
|
||||
import { login as _login } from '../../redux/actions/userActions';
|
||||
import { authenticate } from "../../api";
|
||||
import { login as _login } from "../../redux/actions/userActions";
|
||||
import {
|
||||
HOST,
|
||||
DEMO_USER,
|
||||
DEMO_WAKATIME_USER,
|
||||
DEMO_REPO,
|
||||
DEMO_GIST,
|
||||
} from '../../constants';
|
||||
import { CardTypes } from '../../utils';
|
||||
import { DEFAULT_OPTION as STATS_DEFAULT_RANK } from '../../components/Home/StatsRankSection';
|
||||
import { DEFAULT_OPTION as LANGUAGES_DEFAULT_LAYOUT } from '../../components/Home/LanguagesLayoutSection';
|
||||
import { DEFAULT_OPTION as WAKATIME_DEFAULT_LAYOUT } from '../../components/Home/WakatimeLayoutSection';
|
||||
} from "../../constants";
|
||||
import { CardTypes } from "../../utils";
|
||||
import { DEFAULT_OPTION as STATS_DEFAULT_RANK } from "../../components/Home/StatsRankSection";
|
||||
import { DEFAULT_OPTION as LANGUAGES_DEFAULT_LAYOUT } from "../../components/Home/LanguagesLayoutSection";
|
||||
import { DEFAULT_OPTION as WAKATIME_DEFAULT_LAYOUT } from "../../components/Home/WakatimeLayoutSection";
|
||||
import {
|
||||
useUserId,
|
||||
useIsAuthenticated,
|
||||
usePrivateAccess,
|
||||
} from '../../redux/selectors/userSelectors';
|
||||
import axios from 'axios';
|
||||
} from "../../redux/selectors/userSelectors";
|
||||
import axios from "axios";
|
||||
|
||||
const HomeScreen = ({ stage, setStage }) => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
@@ -49,7 +49,7 @@ const HomeScreen = ({ stage, setStage }) => {
|
||||
const [gist, setGist] = useState(DEMO_GIST);
|
||||
const [wakatimeUser, setWakatimeUser] = useState(DEMO_WAKATIME_USER);
|
||||
|
||||
const [selectedCard, setSelectedCard] = useState('stats');
|
||||
const [selectedCard, setSelectedCard] = useState("stats");
|
||||
|
||||
useEffect(() => {
|
||||
setSelectedUserId(userId);
|
||||
@@ -68,7 +68,7 @@ const HomeScreen = ({ stage, setStage }) => {
|
||||
const [showTitle, setShowTitle] = useState(true);
|
||||
const [showOwner, setShowOwner] = useState(false);
|
||||
const [descriptionLines, setDescriptionLines] = useState();
|
||||
const [customTitle, setCustomTitle] = useState('');
|
||||
const [customTitle, setCustomTitle] = useState("");
|
||||
const [langsCount, setLangsCount] = useState();
|
||||
const [showAllStats, setShowAllStats] = useState(false);
|
||||
const [showIcons, setShowIcons] = useState(false);
|
||||
@@ -91,11 +91,11 @@ const HomeScreen = ({ stage, setStage }) => {
|
||||
setSelectedLanguagesLayout(LANGUAGES_DEFAULT_LAYOUT);
|
||||
}
|
||||
|
||||
if (theme === 'default' || theme === 'default_repocard') {
|
||||
if (theme === "default" || theme === "default_repocard") {
|
||||
if (selectedCard === CardTypes.PIN || selectedCard === CardTypes.GIST) {
|
||||
setTheme('default_repocard');
|
||||
setTheme("default_repocard");
|
||||
} else {
|
||||
setTheme('default');
|
||||
setTheme("default");
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -104,7 +104,7 @@ const HomeScreen = ({ stage, setStage }) => {
|
||||
resetCustomization();
|
||||
}, [selectedCard]);
|
||||
|
||||
let fullSuffix = `${selectedCard === CardTypes.STATS ? '' : '/' + selectedCard}?`;
|
||||
let fullSuffix = `${selectedCard === CardTypes.STATS ? "" : "/" + selectedCard}?`;
|
||||
|
||||
switch (selectedCard) {
|
||||
case CardTypes.STATS:
|
||||
@@ -148,14 +148,14 @@ const HomeScreen = ({ stage, setStage }) => {
|
||||
selectedCard === CardTypes.TOP_LANGS ||
|
||||
selectedCard === CardTypes.WAKATIME)
|
||||
) {
|
||||
fullSuffix += '&hide_title=true';
|
||||
fullSuffix += "&hide_title=true";
|
||||
}
|
||||
|
||||
if (
|
||||
showOwner &&
|
||||
(selectedCard === CardTypes.PIN || selectedCard === CardTypes.GIST)
|
||||
) {
|
||||
fullSuffix += '&show_owner=true';
|
||||
fullSuffix += "&show_owner=true";
|
||||
}
|
||||
|
||||
if (descriptionLines && selectedCard === CardTypes.PIN) {
|
||||
@@ -204,16 +204,16 @@ const HomeScreen = ({ stage, setStage }) => {
|
||||
}
|
||||
|
||||
// for stage four
|
||||
const [theme, setTheme] = useState('default');
|
||||
const [theme, setTheme] = useState("default");
|
||||
let themeSuffix = fullSuffix;
|
||||
|
||||
if (
|
||||
!(
|
||||
(theme === 'default' &&
|
||||
(theme === "default" &&
|
||||
[CardTypes.STATS, CardTypes.TOP_LANGS, CardTypes.WAKATIME].includes(
|
||||
selectedCard,
|
||||
)) ||
|
||||
(theme === 'default_repocard' &&
|
||||
(theme === "default_repocard" &&
|
||||
[CardTypes.PIN, CardTypes.GIST].includes(selectedCard))
|
||||
)
|
||||
) {
|
||||
@@ -221,7 +221,7 @@ const HomeScreen = ({ stage, setStage }) => {
|
||||
}
|
||||
|
||||
// for stage five
|
||||
const [gistUrl, setGistUrl] = useState('');
|
||||
const [gistUrl, setGistUrl] = useState("");
|
||||
|
||||
let guestHint;
|
||||
switch (selectedCard) {
|
||||
@@ -247,7 +247,7 @@ const HomeScreen = ({ stage, setStage }) => {
|
||||
return result.data.html_url;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return '';
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
@@ -274,9 +274,9 @@ const HomeScreen = ({ stage, setStage }) => {
|
||||
const url = window.location.href;
|
||||
|
||||
// If Github API returns the code parameter
|
||||
if (url.includes('code=')) {
|
||||
const tempPrivateAccess = url.includes('private');
|
||||
const newUrl = url.split('?code=');
|
||||
if (url.includes("code=")) {
|
||||
const tempPrivateAccess = url.includes("private");
|
||||
const newUrl = url.split("?code=");
|
||||
const redirect = `${url.split(HOST)[0]}${HOST}/frontend`;
|
||||
window.history.pushState({}, null, redirect);
|
||||
setIsLoading(true);
|
||||
@@ -313,11 +313,11 @@ const HomeScreen = ({ stage, setStage }) => {
|
||||
<div className="text-2xl text-gray-600 font-semibold">
|
||||
{
|
||||
[
|
||||
'Login',
|
||||
'Select a Card',
|
||||
'Modify Card Parameters',
|
||||
'Choose a Theme',
|
||||
'Display your Card',
|
||||
"Login",
|
||||
"Select a Card",
|
||||
"Modify Card Parameters",
|
||||
"Choose a Theme",
|
||||
"Display your Card",
|
||||
][stage]
|
||||
}
|
||||
</div>
|
||||
@@ -325,7 +325,7 @@ const HomeScreen = ({ stage, setStage }) => {
|
||||
{stage === 0 && isAuthenticated ? (
|
||||
<div>
|
||||
<p>
|
||||
You are logged in as{' '}
|
||||
You are logged in as{" "}
|
||||
<a
|
||||
href={`https://github.com/${userId}`}
|
||||
target="_blank"
|
||||
@@ -338,12 +338,12 @@ const HomeScreen = ({ stage, setStage }) => {
|
||||
<p>
|
||||
{privateAccess ? (
|
||||
<>
|
||||
You granted GitHub-Stats-Extended access to both your{' '}
|
||||
You granted GitHub-Stats-Extended access to both your{" "}
|
||||
<b>public and private</b> contributions.
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
You granted GitHub-Stats-Extended access to your{' '}
|
||||
You granted GitHub-Stats-Extended access to your{" "}
|
||||
<b>public</b> contributions.
|
||||
</>
|
||||
)}
|
||||
@@ -351,11 +351,11 @@ const HomeScreen = ({ stage, setStage }) => {
|
||||
</div>
|
||||
) : (
|
||||
[
|
||||
'',
|
||||
'You will be able to customize your card in future steps.',
|
||||
'',
|
||||
'',
|
||||
'Display the finished card on GitHub, Twitter/X, LinkedIn, or anywhere else!',
|
||||
"",
|
||||
"You will be able to customize your card in future steps.",
|
||||
"",
|
||||
"",
|
||||
"Display the finished card on GitHub, Twitter/X, LinkedIn, or anywhere else!",
|
||||
][stage]
|
||||
)}
|
||||
</div>
|
||||
@@ -439,7 +439,7 @@ const HomeScreen = ({ stage, setStage }) => {
|
||||
return `https://${HOST}/api${themeSuffix}`;
|
||||
case CardTypes.PIN:
|
||||
let myRepo = repo;
|
||||
if (!myRepo.includes('/')) {
|
||||
if (!myRepo.includes("/")) {
|
||||
myRepo = `${userId}/${myRepo}`;
|
||||
}
|
||||
return `https://github.com/${myRepo}`;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import HomeScreen from './Home';
|
||||
import HomeScreen from "./Home";
|
||||
|
||||
export default HomeScreen;
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { CheckboxSection, Image } from '../../../components';
|
||||
import { CardTypes } from '../../../utils';
|
||||
import TextSection from '../../../components/Home/TextSection';
|
||||
import NumericSection from '../../../components/Home/NumericSection';
|
||||
import StatsRankSection from '../../../components/Home/StatsRankSection';
|
||||
import LanguagesLayoutSection from '../../../components/Home/LanguagesLayoutSection';
|
||||
import WakatimeLayoutSection from '../../../components/Home/WakatimeLayoutSection';
|
||||
import { CheckboxSection, Image } from "../../../components";
|
||||
import { CardTypes } from "../../../utils";
|
||||
import TextSection from "../../../components/Home/TextSection";
|
||||
import NumericSection from "../../../components/Home/NumericSection";
|
||||
import StatsRankSection from "../../../components/Home/StatsRankSection";
|
||||
import LanguagesLayoutSection from "../../../components/Home/LanguagesLayoutSection";
|
||||
import WakatimeLayoutSection from "../../../components/Home/WakatimeLayoutSection";
|
||||
import {
|
||||
DEMO_GIST,
|
||||
DEMO_REPO,
|
||||
DEMO_USER,
|
||||
DEMO_WAKATIME_USER,
|
||||
} from '../../../constants';
|
||||
import { useIsAuthenticated } from '../../../redux/selectors/userSelectors';
|
||||
} from "../../../constants";
|
||||
import { useIsAuthenticated } from "../../../redux/selectors/userSelectors";
|
||||
|
||||
const CustomizeStage = ({
|
||||
selectedCard,
|
||||
@@ -70,7 +70,7 @@ const CustomizeStage = ({
|
||||
<br />
|
||||
{!isAuthenticated && (
|
||||
<>
|
||||
Please{' '}
|
||||
Please{" "}
|
||||
<a
|
||||
href="#"
|
||||
onClick={(e) => {
|
||||
@@ -80,7 +80,7 @@ const CustomizeStage = ({
|
||||
className="underline text-blue-900"
|
||||
>
|
||||
log in
|
||||
</a>{' '}
|
||||
</a>{" "}
|
||||
to change the username.
|
||||
</>
|
||||
)}
|
||||
@@ -91,14 +91,14 @@ const CustomizeStage = ({
|
||||
setValue={setSelectedUserId}
|
||||
onPaste={(e) => {
|
||||
e.preventDefault();
|
||||
let newValue = e.clipboardData.getData('text');
|
||||
let newValue = e.clipboardData.getData("text");
|
||||
// if the user pasted a full GitHub URL, extract username
|
||||
if (newValue.endsWith('/')) {
|
||||
if (newValue.endsWith("/")) {
|
||||
newValue = newValue.slice(0, -1);
|
||||
}
|
||||
let parts = newValue.split('/');
|
||||
let parts = newValue.split("/");
|
||||
if (parts.length > 1) {
|
||||
newValue = parts.slice(-1).join('/');
|
||||
newValue = parts.slice(-1).join("/");
|
||||
}
|
||||
setSelectedUserId(newValue);
|
||||
}}
|
||||
@@ -114,7 +114,7 @@ const CustomizeStage = ({
|
||||
<br />
|
||||
{!isAuthenticated && (
|
||||
<>
|
||||
Please{' '}
|
||||
Please{" "}
|
||||
<a
|
||||
href="#"
|
||||
onClick={(e) => {
|
||||
@@ -124,7 +124,7 @@ const CustomizeStage = ({
|
||||
className="underline text-blue-900"
|
||||
>
|
||||
log in
|
||||
</a>{' '}
|
||||
</a>{" "}
|
||||
to change the repo.
|
||||
</>
|
||||
)}
|
||||
@@ -135,14 +135,14 @@ const CustomizeStage = ({
|
||||
setValue={setRepo}
|
||||
onPaste={(e) => {
|
||||
e.preventDefault();
|
||||
let newValue = e.clipboardData.getData('text');
|
||||
let newValue = e.clipboardData.getData("text");
|
||||
// if the user pasted a full GitHub URL, extract owner/repo
|
||||
if (newValue.endsWith('/')) {
|
||||
if (newValue.endsWith("/")) {
|
||||
newValue = newValue.slice(0, -1);
|
||||
}
|
||||
let parts = newValue.split('/');
|
||||
let parts = newValue.split("/");
|
||||
if (parts.length > 2) {
|
||||
newValue = parts.slice(-2).join('/');
|
||||
newValue = parts.slice(-2).join("/");
|
||||
}
|
||||
setRepo(newValue);
|
||||
}}
|
||||
@@ -158,7 +158,7 @@ const CustomizeStage = ({
|
||||
<br />
|
||||
{!isAuthenticated && (
|
||||
<>
|
||||
Please{' '}
|
||||
Please{" "}
|
||||
<a
|
||||
href="#"
|
||||
onClick={(e) => {
|
||||
@@ -168,7 +168,7 @@ const CustomizeStage = ({
|
||||
className="underline text-blue-900"
|
||||
>
|
||||
log in
|
||||
</a>{' '}
|
||||
</a>{" "}
|
||||
to change the gist id.
|
||||
</>
|
||||
)}
|
||||
@@ -179,14 +179,14 @@ const CustomizeStage = ({
|
||||
setValue={setGist}
|
||||
onPaste={(e) => {
|
||||
e.preventDefault();
|
||||
let newValue = e.clipboardData.getData('text');
|
||||
let newValue = e.clipboardData.getData("text");
|
||||
// if the user pasted a full GitHub URL, extract Gist ID
|
||||
if (newValue.endsWith('/')) {
|
||||
if (newValue.endsWith("/")) {
|
||||
newValue = newValue.slice(0, -1);
|
||||
}
|
||||
let parts = newValue.split('/');
|
||||
let parts = newValue.split("/");
|
||||
if (parts.length > 1) {
|
||||
newValue = parts.slice(-1).join('/');
|
||||
newValue = parts.slice(-1).join("/");
|
||||
}
|
||||
setGist(newValue);
|
||||
}}
|
||||
@@ -198,14 +198,14 @@ const CustomizeStage = ({
|
||||
title="WakaTime Username"
|
||||
description={
|
||||
<>
|
||||
Set your{' '}
|
||||
Set your{" "}
|
||||
<a
|
||||
href="https://wakatime.com/"
|
||||
target="_blank"
|
||||
className="underline text-blue-900"
|
||||
>
|
||||
WakaTime
|
||||
</a>{' '}
|
||||
</a>{" "}
|
||||
username to fetch your stats.
|
||||
</>
|
||||
}
|
||||
@@ -336,14 +336,14 @@ const CustomizeStage = ({
|
||||
/>
|
||||
)}
|
||||
<div className="pl-10 pr-10">
|
||||
For more customization options check the{' '}
|
||||
For more customization options check the{" "}
|
||||
<a
|
||||
href="https://github.com/stats-organization/github-stats-extended/blob/master/docs/advanced_documentation.md"
|
||||
target="_blank"
|
||||
className="underline text-blue-900"
|
||||
>
|
||||
customization documentation
|
||||
</a>{' '}
|
||||
</a>{" "}
|
||||
after you copied your card URL in step 5.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/* eslint-disable react/no-array-index-key */
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { toast } from 'react-toastify';
|
||||
import 'react-toastify/dist/ReactToastify.css';
|
||||
import { toast } from "react-toastify";
|
||||
import "react-toastify/dist/ReactToastify.css";
|
||||
|
||||
import { saveSvgAsPng } from 'save-svg-as-png';
|
||||
import { saveSvgAsPng } from "save-svg-as-png";
|
||||
|
||||
import { Button, Image } from '../../../components';
|
||||
import { classnames } from '../../../utils';
|
||||
import { HOST } from '../../../constants';
|
||||
import { Button, Image } from "../../../components";
|
||||
import { classnames } from "../../../utils";
|
||||
import { HOST } from "../../../constants";
|
||||
|
||||
const DisplayStage = ({ filename, link, themeSuffix, guestHint }) => {
|
||||
const card = themeSuffix.split('?')[0];
|
||||
const card = themeSuffix.split("?")[0];
|
||||
|
||||
const downloadPNG = () => {
|
||||
saveSvgAsPng(
|
||||
document.getElementById('svgWrapper').shadowRoot.firstElementChild
|
||||
document.getElementById("svgWrapper").shadowRoot.firstElementChild
|
||||
.firstElementChild,
|
||||
`${filename}.png`,
|
||||
{
|
||||
@@ -31,8 +31,8 @@ const DisplayStage = ({ filename, link, themeSuffix, guestHint }) => {
|
||||
navigator.clipboard.writeText(
|
||||
`[](${link})`,
|
||||
);
|
||||
toast.info('Copied to Clipboard!', {
|
||||
position: 'bottom-right',
|
||||
toast.info("Copied to Clipboard!", {
|
||||
position: "bottom-right",
|
||||
autoClose: 1500,
|
||||
hideProgressBar: true,
|
||||
closeOnClick: false,
|
||||
@@ -44,8 +44,8 @@ const DisplayStage = ({ filename, link, themeSuffix, guestHint }) => {
|
||||
|
||||
const copyUrl = () => {
|
||||
navigator.clipboard.writeText(`https://${HOST}/api${themeSuffix}`);
|
||||
toast.info('Copied to Clipboard!', {
|
||||
position: 'bottom-right',
|
||||
toast.info("Copied to Clipboard!", {
|
||||
position: "bottom-right",
|
||||
autoClose: 1500,
|
||||
hideProgressBar: true,
|
||||
closeOnClick: false,
|
||||
@@ -62,20 +62,20 @@ const DisplayStage = ({ filename, link, themeSuffix, guestHint }) => {
|
||||
<div className="flex flex-col items-center">
|
||||
{[
|
||||
{
|
||||
title: 'Copy Markdown',
|
||||
title: "Copy Markdown",
|
||||
highlight: true,
|
||||
onClick: copyMarkdown,
|
||||
},
|
||||
{ title: 'Copy URL', highlight: false, onClick: copyUrl },
|
||||
{ title: 'Download PNG', highlight: false, onClick: downloadPNG },
|
||||
{ title: "Copy URL", highlight: false, onClick: copyUrl },
|
||||
{ title: "Download PNG", highlight: false, onClick: downloadPNG },
|
||||
].map((item, index) => (
|
||||
<Button
|
||||
key={index}
|
||||
className={classnames(
|
||||
'm-4 w-60 flex justify-center',
|
||||
"m-4 w-60 flex justify-center",
|
||||
item.highlight
|
||||
? 'bg-blue-500 hover:bg-blue-600 text-white'
|
||||
: 'bg-white hover:bg-gray-100 text-black',
|
||||
? "bg-blue-500 hover:bg-blue-600 text-white"
|
||||
: "bg-white hover:bg-gray-100 text-black",
|
||||
)}
|
||||
onClick={item.onClick}
|
||||
>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/* eslint-disable react/no-array-index-key */
|
||||
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { useDispatch } from "react-redux";
|
||||
|
||||
import { Button, Image } from '../../../components';
|
||||
import { classnames } from '../../../utils';
|
||||
import { Button, Image } from "../../../components";
|
||||
import { classnames } from "../../../utils";
|
||||
import {
|
||||
CLIENT_ID,
|
||||
DEMO_GIST,
|
||||
@@ -15,16 +15,16 @@ import {
|
||||
GITHUB_PRIVATE_AUTH_URL,
|
||||
GITHUB_PUBLIC_AUTH_URL,
|
||||
HOST,
|
||||
} from '../../../constants';
|
||||
import { FaGithub as GithubIcon } from 'react-icons/fa';
|
||||
import { logout as _logout } from '../../../redux/actions/userActions';
|
||||
} from "../../../constants";
|
||||
import { FaGithub as GithubIcon } from "react-icons/fa";
|
||||
import { logout as _logout } from "../../../redux/actions/userActions";
|
||||
import {
|
||||
useIsAuthenticated,
|
||||
usePrivateAccess,
|
||||
useUserId,
|
||||
useUserKey,
|
||||
} from '../../../redux/selectors/userSelectors';
|
||||
import { deleteAccount } from '../../../api';
|
||||
} from "../../../redux/selectors/userSelectors";
|
||||
import { deleteAccount } from "../../../api";
|
||||
|
||||
const LoginStage = ({ setCurrItem }) => {
|
||||
const userId = useUserId(null);
|
||||
@@ -59,10 +59,10 @@ const LoginStage = ({ setCurrItem }) => {
|
||||
}
|
||||
|
||||
// Bind the event listener
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
document.addEventListener("mousedown", handleClickOutside);
|
||||
return () => {
|
||||
// Unbind the event listener on clean up
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
document.removeEventListener("mousedown", handleClickOutside);
|
||||
};
|
||||
}, [ref]);
|
||||
}
|
||||
@@ -99,12 +99,12 @@ const LoginStage = ({ setCurrItem }) => {
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-wrap">
|
||||
<div className={classnames(deleteModal ? 'opacity-25' : '', 'md:flex')}>
|
||||
<div className={classnames(deleteModal ? "opacity-25" : "", "md:flex")}>
|
||||
<div className="lg:block lg:w-3/5 lg:p-8">
|
||||
<div
|
||||
className={classnames(
|
||||
'bg-gray-200 rounded-sm w-full h-full m-auto p-8 shadow',
|
||||
'lg:h-auto',
|
||||
"bg-gray-200 rounded-sm w-full h-full m-auto p-8 shadow",
|
||||
"lg:h-auto",
|
||||
)}
|
||||
>
|
||||
{isAuthenticated ? (
|
||||
@@ -243,9 +243,9 @@ const LoginStage = ({ setCurrItem }) => {
|
||||
key={index}
|
||||
style={{
|
||||
left: `${x}%`,
|
||||
position: 'relative',
|
||||
zoom: '0.5',
|
||||
marginBottom: '1%',
|
||||
position: "relative",
|
||||
zoom: "0.5",
|
||||
marginBottom: "1%",
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
/* eslint-disable react/no-array-index-key */
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { Card } from '../../../components';
|
||||
import { useUserId } from '../../../redux/selectors/userSelectors';
|
||||
import { Card } from "../../../components";
|
||||
import { useUserId } from "../../../redux/selectors/userSelectors";
|
||||
import {
|
||||
DEMO_GIST,
|
||||
DEMO_REPO,
|
||||
DEMO_USER,
|
||||
DEMO_WAKATIME_USER,
|
||||
} from '../../../constants';
|
||||
import { CardTypes } from '../../../utils';
|
||||
} from "../../../constants";
|
||||
import { CardTypes } from "../../../utils";
|
||||
|
||||
const SelectCardStage = ({ selectedCard, setSelectedCard, setStage }) => {
|
||||
return (
|
||||
<div className="w-full flex flex-wrap">
|
||||
{[
|
||||
{
|
||||
title: 'GitHub Stats Card',
|
||||
description: 'your overall GitHub statistics',
|
||||
title: "GitHub Stats Card",
|
||||
description: "your overall GitHub statistics",
|
||||
demoImageSrc: `?username=${useUserId(DEMO_USER)}&include_all_commits=true`,
|
||||
cardType: CardTypes.STATS,
|
||||
},
|
||||
{
|
||||
title: 'Top Languages Card',
|
||||
description: 'your most frequently used languages',
|
||||
title: "Top Languages Card",
|
||||
description: "your most frequently used languages",
|
||||
demoImageSrc: `/top-langs?username=${useUserId(DEMO_USER)}&langs_count=4`,
|
||||
cardType: CardTypes.TOP_LANGS,
|
||||
},
|
||||
{
|
||||
title: 'GitHub Extra Pin',
|
||||
title: "GitHub Extra Pin",
|
||||
description:
|
||||
'pin more than 6 repositories in your profile using a GitHub profile readme',
|
||||
"pin more than 6 repositories in your profile using a GitHub profile readme",
|
||||
demoImageSrc: `/pin?repo=${DEMO_REPO}`,
|
||||
cardType: CardTypes.PIN,
|
||||
},
|
||||
{
|
||||
title: 'GitHub Gist Pin',
|
||||
title: "GitHub Gist Pin",
|
||||
description:
|
||||
'pin gists in your GitHub profile using a GitHub profile readme',
|
||||
"pin gists in your GitHub profile using a GitHub profile readme",
|
||||
demoImageSrc: `/gist?id=${DEMO_GIST}`,
|
||||
cardType: CardTypes.GIST,
|
||||
},
|
||||
{
|
||||
title: 'WakaTime Stats Card',
|
||||
description: 'your coding activity from WakaTime',
|
||||
title: "WakaTime Stats Card",
|
||||
description: "your coding activity from WakaTime",
|
||||
demoImageSrc: `/wakatime?username=${DEMO_WAKATIME_USER}&langs_count=6&card_width=450`,
|
||||
cardType: CardTypes.WAKATIME,
|
||||
},
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* eslint-disable react/no-array-index-key */
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { Card } from '../../../components';
|
||||
import { themes } from '../../../backend/themes/index';
|
||||
import { Card } from "../../../components";
|
||||
import { themes } from "../../../backend/themes/index";
|
||||
|
||||
const ThemeStage = ({ theme, setTheme, setStage, fullSuffix }) => {
|
||||
return (
|
||||
@@ -14,12 +14,12 @@ const ThemeStage = ({ theme, setTheme, setStage, fullSuffix }) => {
|
||||
.filter(
|
||||
(myTheme) =>
|
||||
![
|
||||
'merko',
|
||||
'blue-green',
|
||||
'gotham',
|
||||
'blueberry',
|
||||
'outrun',
|
||||
'holi',
|
||||
"merko",
|
||||
"blue-green",
|
||||
"gotham",
|
||||
"blueberry",
|
||||
"outrun",
|
||||
"holi",
|
||||
].includes(myTheme),
|
||||
)
|
||||
.map((myTheme, index) => (
|
||||
@@ -43,14 +43,14 @@ const ThemeStage = ({ theme, setTheme, setStage, fullSuffix }) => {
|
||||
))}
|
||||
</div>
|
||||
<div className="pl-10 pr-10">
|
||||
For more theme options check the{' '}
|
||||
For more theme options check the{" "}
|
||||
<a
|
||||
href="https://github.com/stats-organization/github-stats-extended/blob/master/docs/advanced_documentation.md#themes"
|
||||
target="_blank"
|
||||
className="underline text-blue-900"
|
||||
>
|
||||
customization documentation
|
||||
</a>{' '}
|
||||
</a>{" "}
|
||||
after you copied your card URL in step 5.
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import LoginStage from './Login';
|
||||
import SelectCardStage from './SelectCard';
|
||||
import CustomizeStage from './Customize';
|
||||
import ThemeStage from './Theme';
|
||||
import DisplayStage from './Display';
|
||||
import LoginStage from "./Login";
|
||||
import SelectCardStage from "./SelectCard";
|
||||
import CustomizeStage from "./Customize";
|
||||
import ThemeStage from "./Theme";
|
||||
import DisplayStage from "./Display";
|
||||
|
||||
export {
|
||||
LoginStage,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export const LOGIN = 'LOGIN';
|
||||
export const LOGOUT = 'LOGOUT';
|
||||
export const SET_USER_ACCESS = 'SET_USER_ACCESS';
|
||||
export const LOGIN = "LOGIN";
|
||||
export const LOGOUT = "LOGOUT";
|
||||
export const SET_USER_ACCESS = "SET_USER_ACCESS";
|
||||
|
||||
export function login(userId, userKey) {
|
||||
return { type: LOGIN, payload: { userId, userKey } };
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { combineReducers } from 'redux';
|
||||
import { combineReducers } from "redux";
|
||||
|
||||
import user from './user';
|
||||
import user from "./user";
|
||||
|
||||
export default combineReducers({ user });
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as types from '../actions/userActions';
|
||||
import * as types from "../actions/userActions";
|
||||
|
||||
const initialState = {
|
||||
userId: JSON.parse(localStorage.getItem('userId')) || null,
|
||||
userKey: JSON.parse(localStorage.getItem('userKey')) || null,
|
||||
userId: JSON.parse(localStorage.getItem("userId")) || null,
|
||||
userKey: JSON.parse(localStorage.getItem("userKey")) || null,
|
||||
token: null,
|
||||
privateAccess: null,
|
||||
};
|
||||
@@ -11,8 +11,8 @@ const initialState = {
|
||||
export default (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case types.LOGIN:
|
||||
localStorage.setItem('userId', JSON.stringify(action.payload.userId));
|
||||
localStorage.setItem('userKey', JSON.stringify(action.payload.userKey));
|
||||
localStorage.setItem("userId", JSON.stringify(action.payload.userId));
|
||||
localStorage.setItem("userKey", JSON.stringify(action.payload.userKey));
|
||||
return {
|
||||
...state,
|
||||
userId: action.payload.userId,
|
||||
@@ -21,7 +21,7 @@ export default (state = initialState, action) => {
|
||||
case types.LOGOUT:
|
||||
if (
|
||||
action.payload.userKey !== null &&
|
||||
action.payload.userKey !== JSON.parse(localStorage.getItem('userKey'))
|
||||
action.payload.userKey !== JSON.parse(localStorage.getItem("userKey"))
|
||||
) {
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
export const useUserId = (fallbackUsername) => {
|
||||
return useSelector((state) => state.user.userId) || fallbackUsername;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { applyMiddleware, createStore, compose } from 'redux';
|
||||
import { applyMiddleware, createStore, compose } from "redux";
|
||||
|
||||
import loggerMiddleware from './logger';
|
||||
import rootReducer from './reducers';
|
||||
import { USE_LOGGER } from '../constants';
|
||||
import loggerMiddleware from "./logger";
|
||||
import rootReducer from "./reducers";
|
||||
import { USE_LOGGER } from "../constants";
|
||||
|
||||
export default function configureStore(intialState) {
|
||||
let middlewares = [];
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
export function classnames(...args) {
|
||||
return args.join(' ');
|
||||
return args.join(" ");
|
||||
}
|
||||
|
||||
export const CardTypes = {
|
||||
STATS: 'stats',
|
||||
TOP_LANGS: 'top-langs',
|
||||
PIN: 'pin',
|
||||
GIST: 'gist',
|
||||
WAKATIME: 'wakatime',
|
||||
STATS: "stats",
|
||||
TOP_LANGS: "top-langs",
|
||||
PIN: "pin",
|
||||
GIST: "gist",
|
||||
WAKATIME: "wakatime",
|
||||
};
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import axios from 'axios';
|
||||
import { HOST } from './constants';
|
||||
import axios from "axios";
|
||||
import { HOST } from "./constants";
|
||||
|
||||
const fetchWakatimeStats = async ({ username, api_domain }) => {
|
||||
if (!username) {
|
||||
throw new Error('missing parameter: username');
|
||||
throw new Error("missing parameter: username");
|
||||
}
|
||||
|
||||
const { data } = await axios.get(
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
/* eslint-disable global-require */
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ['./src/**/*.{js,jsx,ts,tsx}'],
|
||||
content: ["./src/**/*.{js,jsx,ts,tsx}"],
|
||||
theme: {
|
||||
screens: {
|
||||
sm: '640px',
|
||||
md: '768px',
|
||||
lg: '1024px',
|
||||
xl: '1280px',
|
||||
'2xl': '1536px',
|
||||
'3xl': '1792px',
|
||||
sm: "640px",
|
||||
md: "768px",
|
||||
lg: "1024px",
|
||||
xl: "1280px",
|
||||
"2xl": "1536px",
|
||||
"3xl": "1792px",
|
||||
},
|
||||
extend: {
|
||||
fontFamily: {
|
||||
typist: ['Playfair Display SC', 'Courier New'],
|
||||
typist: ["Playfair Display SC", "Courier New"],
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [require('daisyui')],
|
||||
plugins: [require("daisyui")],
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"$schema": "https://openapi.vercel.sh/vercel.json",
|
||||
"installCommand": "../../vercel-preparation.sh && pnpm install",
|
||||
"buildCommand": "pnpm run build-trends",
|
||||
"outputDirectory": "build"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user