diff --git a/.env b/.env deleted file mode 100644 index 1d6d1571f..000000000 --- a/.env +++ /dev/null @@ -1,5 +0,0 @@ -NEXT_PUBLIC_APP_NAME = example -NEXT_PUBLIC_BUNDLE_ANALYZER = false -NEXT_PUBLIC_CSS_EXAMPLE_PREFIX = example -NEXT_PUBLIC_CSS_APP_PREFIX = ant -__NEXT_REACT_ROOT = false diff --git a/.env.example b/.env.example new file mode 100644 index 000000000..f65d6cd66 --- /dev/null +++ b/.env.example @@ -0,0 +1,13 @@ +# for handling environment variables +# use .env on every environment +NEXT_PUBLIC_APP_NAME = explorer.aelf.io +NEXT_PUBLIC_BUNDLE_ANALYZER = false +NEXT_PUBLIC_CSS_APP_PREFIX = ant +NEXT_PUBLIC_SENTRY_DSN = your dsn +__NEXT_REACT_ROOT = false +# use .env.local on development +# use .env.production on production +BUILD_ENDPOINT=https://explorer-test.aelf.io +BUILD_ENDPOINT_SOCKET=https://explorer-test.aelf.io +BUILD_ENDPOINT_CMS=https://explorer-test.aelf.io +BUILD_ENDPOINT_CHAIN=https://explorer-test.aelf.io \ No newline at end of file diff --git a/.env.production b/.env.production deleted file mode 100644 index ae38250ee..000000000 --- a/.env.production +++ /dev/null @@ -1,3 +0,0 @@ -BUILD_ENDPOINT=http://172.31.47.238:7101 -BUILD_ENDPOINT_CMS=http://103.61.39.232:1338 -BUILD_ENDPOINT_CHAIN=http://172.31.43.22:8000 \ No newline at end of file diff --git a/.eslintcache b/.eslintcache deleted file mode 100644 index acf45f5a3..000000000 --- a/.eslintcache +++ /dev/null @@ -1 +0,0 @@ -[{"/Users/xiezixin/Documents/work/aelf-block-explorer/src/constants/config/config.ts":"1","/Users/xiezixin/Documents/work/aelf-block-explorer/src/constants/info.ts":"2","/Users/xiezixin/Documents/work/aelf-block-explorer/src/constants/misc.tsx":"3","/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Vote/ElectionNotification/CandidateApplyModal/CandidateApplyModal.js":"4","/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Vote/ElectionNotification/ElectionNotification.js":"5","/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Vote/RedeemModal/index.js":"6","/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Vote/VoteModal/index.js":"7","/Users/xiezixin/Documents/work/aelf-block-explorer/src/pages/proposal/organizations/Organization/index.jsx":"8","/Users/xiezixin/Documents/work/aelf-block-explorer/src/pages/proposal/proposalsDetail/ContractDetail/index.jsx":"9","/Users/xiezixin/Documents/work/aelf-block-explorer/src/utils/formater.js":"10","/Users/xiezixin/Documents/work/aelf-block-explorer/src/components/ChainSelect/ChainSelect.js":"11","/Users/xiezixin/Documents/work/aelf-block-explorer/src/components/PageHead/HeaderTop.tsx":"12","/Users/xiezixin/Documents/work/aelf-block-explorer/src/constants/config/viewer/config.js":"13","/Users/xiezixin/Documents/work/aelf-block-explorer/src/constants/viewerApi.js":"14","/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Home/index.tsx":"15","/Users/xiezixin/Documents/work/aelf-block-explorer/src/pages/_app.tsx":"16","/Users/xiezixin/Documents/work/aelf-block-explorer/src/pages/_proposalApp.tsx":"17","/Users/xiezixin/Documents/work/aelf-block-explorer/src/pages/index.tsx":"18","/Users/xiezixin/Documents/work/aelf-block-explorer/src/components/PageHead/Header.tsx":"19","/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Vote/ElectionNotification/NodeTable/index.js":"20","/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Vote/MyVote/MyVote.js":"21","/Users/xiezixin/Documents/work/aelf-block-explorer/src/utils/axios/index.ts":"22","/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Home/socket/index.tsx":"23","/Users/xiezixin/Documents/work/aelf-block-explorer/src/utils/getCMS.js":"24","/Users/xiezixin/Documents/work/aelf-block-explorer/src/components/Breadcrumb/Breadcrumb.tsx":"25","/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Home/components/LatestInfo.tsx":"26","/Users/xiezixin/Documents/work/aelf-block-explorer/src/utils/deviceCheck.js":"27","/Users/xiezixin/Documents/work/aelf-block-explorer/src/components/CodeBlock/CodeBlock.jsx":"28","/Users/xiezixin/Documents/work/aelf-block-explorer/src/components/Footer/Footer.tsx":"29","/Users/xiezixin/Documents/work/aelf-block-explorer/src/components/PageHead/types.ts":"30","/Users/xiezixin/Documents/work/aelf-block-explorer/src/hooks/Providers/ProviderBasic/index.tsx":"31","/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Home/components/ChainInfo.tsx":"32","/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Home/components/Search.tsx":"33","/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Home/types.ts":"34","/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Resource/components/ResourceMoneyMarket/RealTimeTransactions/RealTimeTransactions.js":"35","/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Resource/components/ResourceMoneyMarket/ResourceTrading/ResourceBuy/ResourceBuy.js":"36","/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Vote/MyVote/MyVoteRecords/index.js":"37","/Users/xiezixin/Documents/work/aelf-block-explorer/src/redux/features/proposal/common.js":"38","/Users/xiezixin/Documents/work/aelf-block-explorer/src/redux/features/smallScreen/isSmallScreen.ts":"39"},{"size":1640,"mtime":1665473730504,"results":"40","hashOfConfig":"41"},{"size":4476,"mtime":1665284195829,"results":"42","hashOfConfig":"41"},{"size":8215,"mtime":1665283592186,"results":"43","hashOfConfig":"41"},{"size":4450,"mtime":1665283652798,"results":"44","hashOfConfig":"41"},{"size":12392,"mtime":1665284048107,"results":"45","hashOfConfig":"41"},{"size":7457,"mtime":1665284103759,"results":"46","hashOfConfig":"41"},{"size":15897,"mtime":1665547057956,"results":"47","hashOfConfig":"41"},{"size":17976,"mtime":1665284290607,"results":"48","hashOfConfig":"41"},{"size":3627,"mtime":1665284561135,"results":"49","hashOfConfig":"41"},{"size":1535,"mtime":1665284434418,"results":"50","hashOfConfig":"41"},{"size":1261,"mtime":1665302468817,"results":"51","hashOfConfig":"41"},{"size":3881,"mtime":1665545575287,"results":"52","hashOfConfig":"41"},{"size":386,"mtime":1665302468818,"results":"53","hashOfConfig":"41"},{"size":1577,"mtime":1665302468818,"results":"54","hashOfConfig":"41"},{"size":8158,"mtime":1665554870724,"results":"55","hashOfConfig":"41"},{"size":4222,"mtime":1665554345957,"results":"56","hashOfConfig":"41"},{"size":5301,"mtime":1665560560316,"results":"57","hashOfConfig":"41"},{"size":6967,"mtime":1665546582411,"results":"58","hashOfConfig":"41"},{"size":12849,"mtime":1665560588455,"results":"59","hashOfConfig":"41"},{"size":16329,"mtime":1665560418410,"results":"60","hashOfConfig":"41"},{"size":8256,"mtime":1665308965679,"results":"61","hashOfConfig":"41"},{"size":4675,"mtime":1665561593398,"results":"62","hashOfConfig":"41"},{"size":789,"mtime":1665546346163,"results":"63","hashOfConfig":"41"},{"size":1017,"mtime":1665383896019,"results":"64","hashOfConfig":"41"},{"size":9065,"mtime":1665557729935,"results":"65","hashOfConfig":"41"},{"size":4072,"mtime":1665546410194,"results":"66","hashOfConfig":"41"},{"size":1208,"mtime":1665466889069,"results":"67","hashOfConfig":"41"},{"size":332,"mtime":1665471036092,"results":"68","hashOfConfig":"41"},{"size":4086,"mtime":1665554740654,"results":"69","hashOfConfig":"41"},{"size":169,"mtime":1665545586054,"results":"70","hashOfConfig":"41"},{"size":372,"mtime":1665545228532,"results":"71","hashOfConfig":"41"},{"size":1751,"mtime":1665546368614,"results":"72","hashOfConfig":"41"},{"size":2890,"mtime":1665546488147,"results":"73","hashOfConfig":"41"},{"size":2967,"mtime":1665546201557,"results":"74","hashOfConfig":"41"},{"size":5231,"mtime":1665560406117,"results":"75","hashOfConfig":"41"},{"size":18506,"mtime":1665555212652,"results":"76","hashOfConfig":"41"},{"size":5557,"mtime":1665560441973,"results":"77","hashOfConfig":"41"},{"size":4387,"mtime":1665560552740,"results":"78","hashOfConfig":"41"},{"size":790,"mtime":1665560083663,"results":"79","hashOfConfig":"41"},{"filePath":"80","messages":"81","suppressedMessages":"82","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"2gb28k",{"filePath":"83","messages":"84","suppressedMessages":"85","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"86","messages":"87","suppressedMessages":"88","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"89","messages":"90","suppressedMessages":"91","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"92","messages":"93","suppressedMessages":"94","errorCount":0,"fatalErrorCount":0,"warningCount":4,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"95","messages":"96","suppressedMessages":"97","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"98","messages":"99","suppressedMessages":"100","errorCount":0,"fatalErrorCount":0,"warningCount":20,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"101","messages":"102","suppressedMessages":"103","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"104","messages":"105","suppressedMessages":"106","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"107","messages":"108","suppressedMessages":"109","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"110","messages":"111","suppressedMessages":"112","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"113","messages":"114","suppressedMessages":"115","errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"116","messages":"117","suppressedMessages":"118","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"119","messages":"120","suppressedMessages":"121","errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"122","messages":"123","suppressedMessages":"124","errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"125","messages":"126","suppressedMessages":"127","errorCount":0,"fatalErrorCount":0,"warningCount":5,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"128","messages":"129","suppressedMessages":"130","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"131","messages":"132","suppressedMessages":"133","errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"134","messages":"135","suppressedMessages":"136","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"137","messages":"138","suppressedMessages":"139","errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"140","messages":"141","suppressedMessages":"142","errorCount":0,"fatalErrorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"143","messages":"144","suppressedMessages":"145","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"146","messages":"147","suppressedMessages":"148","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"149","messages":"150","suppressedMessages":"151","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"152","messages":"153","suppressedMessages":"154","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"155","messages":"156","suppressedMessages":"157","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"158","messages":"159","suppressedMessages":"160","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"161","messages":"162","suppressedMessages":"163","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"164","messages":"165","suppressedMessages":"166","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"167","messages":"168","suppressedMessages":"169","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"170","messages":"171","suppressedMessages":"172","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"173","messages":"174","suppressedMessages":"175","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"176","messages":"177","suppressedMessages":"178","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"179","messages":"180","suppressedMessages":"181","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"182","messages":"183","suppressedMessages":"184","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"185","messages":"186","suppressedMessages":"187","errorCount":0,"fatalErrorCount":0,"warningCount":5,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"188","messages":"189","suppressedMessages":"190","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"191","messages":"192","suppressedMessages":"193","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"194","messages":"195","suppressedMessages":"196","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/xiezixin/Documents/work/aelf-block-explorer/src/constants/config/config.ts",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/constants/info.ts",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/constants/misc.tsx",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Vote/ElectionNotification/CandidateApplyModal/CandidateApplyModal.js",[],["197"],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Vote/ElectionNotification/ElectionNotification.js",["198","199","200","201"],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Vote/RedeemModal/index.js",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Vote/VoteModal/index.js",["202","203","204","205","206","207","208","209","210","211","212","213","214","215","216","217","218","219","220","221"],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/pages/proposal/organizations/Organization/index.jsx",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/pages/proposal/proposalsDetail/ContractDetail/index.jsx",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/utils/formater.js",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/components/ChainSelect/ChainSelect.js",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/components/PageHead/HeaderTop.tsx",["222","223"],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/constants/config/viewer/config.js",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/constants/viewerApi.js",["224"],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Home/index.tsx",["225","226"],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/pages/_app.tsx",["227","228","229","230","231"],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/pages/_proposalApp.tsx",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/pages/index.tsx",["232","233"],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/components/PageHead/Header.tsx",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Vote/ElectionNotification/NodeTable/index.js",["234"],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Vote/MyVote/MyVote.js",["235","236","237"],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/utils/axios/index.ts",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Home/socket/index.tsx",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/utils/getCMS.js",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/components/Breadcrumb/Breadcrumb.tsx",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Home/components/LatestInfo.tsx",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/utils/deviceCheck.js",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/components/CodeBlock/CodeBlock.jsx",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/components/Footer/Footer.tsx",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/components/PageHead/types.ts",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/hooks/Providers/ProviderBasic/index.tsx",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Home/components/ChainInfo.tsx",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Home/components/Search.tsx",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Home/types.ts",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Resource/components/ResourceMoneyMarket/RealTimeTransactions/RealTimeTransactions.js",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Resource/components/ResourceMoneyMarket/ResourceTrading/ResourceBuy/ResourceBuy.js",["238","239","240","241","242"],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/page-components/Vote/MyVote/MyVoteRecords/index.js",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/redux/features/proposal/common.js",[],[],"/Users/xiezixin/Documents/work/aelf-block-explorer/src/redux/features/smallScreen/isSmallScreen.ts",[],[],{"ruleId":"243","severity":2,"message":"244","line":106,"column":26,"nodeType":"245","messageId":"246","endLine":117,"endColumn":7,"suppressions":"247"},{"ruleId":"248","severity":1,"message":"249","line":144,"column":22,"nodeType":"250","messageId":"251","endLine":144,"endColumn":31},{"ruleId":"248","severity":1,"message":"252","line":144,"column":33,"nodeType":"250","messageId":"251","endLine":144,"endColumn":42},{"ruleId":"248","severity":1,"message":"253","line":373,"column":13,"nodeType":"250","messageId":"251","endLine":373,"endColumn":29},{"ruleId":"248","severity":1,"message":"254","line":373,"column":31,"nodeType":"250","messageId":"251","endLine":373,"endColumn":49},{"ruleId":"248","severity":1,"message":"255","line":36,"column":7,"nodeType":"250","messageId":"251","endLine":36,"endColumn":27},{"ruleId":"248","severity":1,"message":"256","line":44,"column":7,"nodeType":"250","messageId":"251","endLine":44,"endColumn":23},{"ruleId":"248","severity":1,"message":"257","line":123,"column":7,"nodeType":"250","messageId":"251","endLine":123,"endColumn":18},{"ruleId":"248","severity":1,"message":"258","line":152,"column":7,"nodeType":"250","messageId":"251","endLine":152,"endColumn":24},{"ruleId":"248","severity":1,"message":"259","line":154,"column":7,"nodeType":"250","messageId":"251","endLine":154,"endColumn":22},{"ruleId":"248","severity":1,"message":"260","line":155,"column":7,"nodeType":"250","messageId":"251","endLine":155,"endColumn":15},{"ruleId":"248","severity":1,"message":"261","line":156,"column":7,"nodeType":"250","messageId":"251","endLine":156,"endColumn":27},{"ruleId":"248","severity":1,"message":"262","line":157,"column":7,"nodeType":"250","messageId":"251","endLine":157,"endColumn":25},{"ruleId":"248","severity":1,"message":"263","line":159,"column":7,"nodeType":"250","messageId":"251","endLine":159,"endColumn":31},{"ruleId":"248","severity":1,"message":"264","line":160,"column":7,"nodeType":"250","messageId":"251","endLine":160,"endColumn":22},{"ruleId":"248","severity":1,"message":"265","line":163,"column":7,"nodeType":"250","messageId":"251","endLine":163,"endColumn":32},{"ruleId":"248","severity":1,"message":"266","line":166,"column":7,"nodeType":"250","messageId":"251","endLine":166,"endColumn":22},{"ruleId":"248","severity":1,"message":"267","line":171,"column":11,"nodeType":"250","messageId":"251","endLine":171,"endColumn":18},{"ruleId":"248","severity":1,"message":"268","line":173,"column":11,"nodeType":"250","messageId":"251","endLine":173,"endColumn":38},{"ruleId":"248","severity":1,"message":"269","line":180,"column":11,"nodeType":"250","messageId":"251","endLine":180,"endColumn":33},{"ruleId":"248","severity":1,"message":"270","line":193,"column":11,"nodeType":"250","messageId":"251","endLine":193,"endColumn":27},{"ruleId":"248","severity":1,"message":"271","line":357,"column":8,"nodeType":"250","messageId":"251","endLine":357,"endColumn":11},{"ruleId":"248","severity":1,"message":"272","line":418,"column":83,"nodeType":"250","messageId":"251","endLine":418,"endColumn":100},{"ruleId":"248","severity":1,"message":"266","line":418,"column":102,"nodeType":"250","messageId":"251","endLine":418,"endColumn":117},{"ruleId":"248","severity":1,"message":"273","line":462,"column":33,"nodeType":"250","messageId":"251","endLine":462,"endColumn":38},{"ruleId":"274","severity":1,"message":"275","line":73,"column":15,"nodeType":"276","endLine":73,"endColumn":38},{"ruleId":"277","severity":1,"message":"278","line":73,"column":15,"nodeType":"276","endLine":73,"endColumn":38},{"ruleId":"279","severity":1,"message":"280","line":36,"column":1,"nodeType":"281","endLine":39,"endColumn":3},{"ruleId":"274","severity":1,"message":"275","line":212,"column":13,"nodeType":"276","endLine":212,"endColumn":36},{"ruleId":"277","severity":1,"message":"278","line":212,"column":13,"nodeType":"276","endLine":212,"endColumn":36},{"ruleId":"282","severity":1,"message":"283","line":58,"column":37,"nodeType":"284","messageId":"285","endLine":62,"endColumn":8},{"ruleId":"282","severity":1,"message":"283","line":71,"column":35,"nodeType":"284","messageId":"285","endLine":75,"endColumn":6},{"ruleId":"248","severity":1,"message":"286","line":79,"column":16,"nodeType":"250","messageId":"251","endLine":79,"endColumn":30},{"ruleId":"248","severity":1,"message":"287","line":79,"column":31,"nodeType":"250","messageId":"251","endLine":79,"endColumn":51},{"ruleId":"248","severity":1,"message":"288","line":109,"column":9,"nodeType":"250","messageId":"251","endLine":109,"endColumn":13},{"ruleId":"248","severity":1,"message":"289","line":125,"column":7,"nodeType":"250","messageId":"251","endLine":125,"endColumn":23},{"ruleId":"248","severity":1,"message":"290","line":166,"column":7,"nodeType":"250","messageId":"251","endLine":166,"endColumn":20},{"ruleId":"248","severity":1,"message":"252","line":65,"column":33,"nodeType":"250","messageId":"251","endLine":65,"endColumn":42},{"ruleId":"248","severity":1,"message":"252","line":45,"column":33,"nodeType":"250","messageId":"251","endLine":45,"endColumn":42},{"ruleId":"248","severity":1,"message":"291","line":59,"column":20,"nodeType":"250","messageId":"251","endLine":59,"endColumn":25},{"ruleId":"248","severity":1,"message":"292","line":90,"column":15,"nodeType":"250","messageId":"251","endLine":90,"endColumn":20},{"ruleId":"248","severity":1,"message":"291","line":334,"column":20,"nodeType":"250","messageId":"251","endLine":334,"endColumn":25},{"ruleId":"248","severity":1,"message":"293","line":353,"column":46,"nodeType":"250","messageId":"251","endLine":353,"endColumn":53},{"ruleId":"248","severity":1,"message":"288","line":407,"column":22,"nodeType":"250","messageId":"251","endLine":407,"endColumn":26},{"ruleId":"248","severity":1,"message":"294","line":408,"column":13,"nodeType":"250","messageId":"251","endLine":408,"endColumn":24},{"ruleId":"248","severity":1,"message":"295","line":408,"column":26,"nodeType":"250","messageId":"251","endLine":408,"endColumn":32},"react/display-name","Component definition is missing display name","CallExpression","noDisplayName",["296"],"@typescript-eslint/no-unused-vars","'prevProps' is defined but never used.","Identifier","unusedVar","'prevState' is defined but never used.","'totalVotesAmount' is assigned a value but never used.","'showDownloadPlugin' is assigned a value but never used.","'switchVotePagination' is assigned a value but never used.","'validateMessages' is assigned a value but never used.","'defaultDate' is assigned a value but never used.","'currentWalletName' is assigned a value but never used.","'voteAmountInput' is assigned a value but never used.","'lockTime' is assigned a value but never used.","'handleLockTimeChange' is assigned a value but never used.","'expiredVotesAmount' is assigned a value but never used.","'withdrawnableVoteRecords' is assigned a value but never used.","'estimatedProfit' is assigned a value but never used.","'voteFromExpiredVoteAmount' is assigned a value but never used.","'changeVoteState' is assigned a value but never used.","'columns' is assigned a value but never used.","'voteFromExpiredRowSelection' is assigned a value but never used.","'switchVoteRowSelection' is assigned a value but never used.","'switchVoteAmount' is assigned a value but never used.","'err' is defined but never used.","'isLockTimeForTest' is assigned a value but never used.","'index' is defined but never used.","@next/next/no-img-element","Do not use `` element. Use `` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element","JSXOpeningElement","jsx-a11y/alt-text","img elements must have an alt prop, either with meaningful text, or an empty string for decorative images.","import/no-anonymous-default-export","Assign object to a variable before exporting as module default","ExportDefaultDeclaration","@typescript-eslint/no-non-null-assertion","Forbidden non-null assertion.","TSNonNullExpression","noNonNull","'fetchChainList' is defined but never used.","'ctx' is defined but never used.","'time' is assigned a value but never used.","'handleSocketData' is assigned a value but never used.","'initSocketSSR' is assigned a value but never used.","'ready' is defined but never used.","'error' is defined but never used.","'appName' is assigned a value but never used.","'buyElfValue' is assigned a value but never used.","'buyNum' is assigned a value but never used.",{"kind":"297","justification":"298"},"directive",""] \ No newline at end of file diff --git a/.gitignore b/.gitignore index ce161b72d..eed934ec0 100755 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,8 @@ yarn-debug.log* yarn-error.log* .pnpm-debug.log* +#env +.env # local env files .env*.local # production env files @@ -38,3 +40,9 @@ yarn-error.log* # shell *.sh + +# cache +.eslintcache + +.sentryclirc +baseConfig.js diff --git a/.sentryclirc.example b/.sentryclirc.example new file mode 100644 index 000000000..dfc962e55 --- /dev/null +++ b/.sentryclirc.example @@ -0,0 +1,14 @@ +[defaults] +url=https://sentry.io/ +project=aelf-block-explorer +org=ienyan + +[auth] +token=your token + +[log] +level=debug + +[http] +verify_ssl=false +check_ssl_revoke=false \ No newline at end of file diff --git a/README.md b/README.md index 526f2396b..3e937f52f 100755 --- a/README.md +++ b/README.md @@ -2,6 +2,10 @@ This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next ## Getting Started +1. add .sentryclirc referring .sentryclirc.example +2. add .env、.env.local refferring .env.example +3. add baseConfig.js including prodRewrites and firebaseConfig, prodRewrites is just like `build/rewrites/development.js`, firebaseConfig can be found at firebase settings. + ```bash # install dependencies $ yarn @@ -29,4 +33,9 @@ The `pages/api` directory is mapped to `/api/*`. Files in this directory are tre ### Production -Change the chain node URL in script such as `yarn build -- --CHAIN_ENDPOINT https://aelf-test-node.aelf.io` +```bash +# Change the chain node URL in script such as +yarn beforeBuild -- --CHAIN_ENDPOINT https://aelf-test-node.aelf.io +yarn build +yarn start +``` diff --git a/build/common.js b/build/common.js index a9350d28e..698545382 100644 --- a/build/common.js +++ b/build/common.js @@ -1,11 +1,63 @@ const rewritesConfig = require('./rewrites/index'); +const { ROOT, getLessVariables } = require('./util.js'); +const path = require('path'); +const { NEXT_PUBLIC_CSS_APP_PREFIX, NEXT_PUBLIC_CSS_EXAMPLE_PREFIX } = process.env; module.exports = { - reactStrictMode: true, + // `Warning: findDOMNode is deprecated in StrictMode.` when use antd + reactStrictMode: false, concurrentFeatures: true, + i18n: { + locales: ['en'], + defaultLocale: 'en', + }, async rewrites() { return rewritesConfig; }, + lessLoaderOptions: { + lessOptions: { + javascriptEnabled: true, + modifyVars: Object.assign(getLessVariables(path.resolve(ROOT, 'src/assets/theme/color.less')), { + '@app-prefix': NEXT_PUBLIC_CSS_EXAMPLE_PREFIX, + '@ant-prefix': NEXT_PUBLIC_CSS_APP_PREFIX, + }), + lessVarsFilePath: 'src/assets/theme/color.less', // optional + lessVarsFilePathAppendToEndOfContent: false, // optional + }, + }, images: { - domains: ['raw.githubusercontent.com'], + disableStaticImages: true, + }, + webpack: function (config) { + config.module.rules.push( + { + test: /\.(jpe?g|png|gif|svg|webp)$/i, + use: [ + { + loader: 'url-loader', + options: { + name: 'static/img/[name]-[hash:5].[ext]', + limit: 8192, + }, + }, + ], + }, + { + test: /\.(woff|woff2|ttf|eot|svg)(#.+)?$/, + use: [ + { + loader: 'url-loader', + options: { + name: 'static/fonts/[name].[ext]', + limit: 8192, + }, + }, + ], + }, + ); + return config; + }, + productionBrowserSourceMaps: true, + sentry: { + hideSourceMaps: true, }, }; diff --git a/build/plugin.js b/build/plugin.js index d00d91311..a09babb0d 100644 --- a/build/plugin.js +++ b/build/plugin.js @@ -1,58 +1,23 @@ -const path = require('path'); const withAntdLess = require('next-plugin-antd-less'); -const { NEXT_PUBLIC_CSS_APP_PREFIX, NEXT_PUBLIC_BUNDLE_ANALYZER, NEXT_PUBLIC_CSS_EXAMPLE_PREFIX } = process.env; +const { NEXT_PUBLIC_BUNDLE_ANALYZER } = process.env; +const { withSentryConfig } = require('@sentry/nextjs'); const withBundleAnalyzer = require('@next/bundle-analyzer')({ enabled: NEXT_PUBLIC_BUNDLE_ANALYZER === 'true', }); +const sentryWebpackPluginOptions = { + // Additional config options for the Sentry Webpack plugin. Keep in mind that + // the following options are set automatically, and overriding them is not + // recommended: + // release, url, org, project, authToken, configFile, stripPrefix, + // urlPrefix, include, ignore -const { ROOT, getLessVariables } = require('./util.js'); - + silent: true, // Suppresses all logs + include: '.next', + configFile: '.sentryclirc', + urlPrefix: '~/_next', +}; module.exports = [ [withBundleAnalyzer], - [ - // withLess, - withAntdLess({ - lessLoaderOptions: { - lessOptions: { - javascriptEnabled: true, - modifyVars: Object.assign(getLessVariables(path.resolve(ROOT, 'src/assets/theme/color.less')), { - '@app-prefix': NEXT_PUBLIC_CSS_EXAMPLE_PREFIX, - '@ant-prefix': NEXT_PUBLIC_CSS_APP_PREFIX, - }), - }, - }, - images: { - disableStaticImages: true, - }, - webpack: function (config) { - config.module.rules.push( - { - test: /\.(jpe?g|png|gif|svg|webp)$/i, - use: [ - { - loader: 'url-loader', - options: { - name: 'static/img/[name]-[hash:5].[ext]', - limit: 8192, - }, - }, - ], - }, - { - test: /\.(woff|woff2|ttf|eot|svg)(#.+)?$/, - use: [ - { - loader: 'url-loader', - options: { - name: 'static/fonts/[name].[ext]', - limit: 8192, - }, - }, - ], - }, - ); - return config; - }, - }), - ], + [withAntdLess], + (nextConfig) => withSentryConfig(nextConfig, sentryWebpackPluginOptions), ]; diff --git a/build/rewrites/development.js b/build/rewrites/development.js index a3a8efc0f..8527f7d23 100644 --- a/build/rewrites/development.js +++ b/build/rewrites/development.js @@ -14,19 +14,19 @@ module.exports = [ destination: 'https://explorer-test.aelf.io/cms/:path*', }, { - source: '/api/blockChain', - destination: 'https://explorer-test.aelf.io/chain/api/blockChain', + source: '/api/blockChain/:path*', + destination: 'http://10.147.20.67:8888/chain/api/blockChain/:path*', }, { source: '/api/:path*', - destination: 'https://explorer-test.aelf.io/api/:path*', + destination: 'http://10.147.20.67:8888/api/:path*', }, { source: '/chain/:path*', - destination: 'https://explorer-test.aelf.io/chain/:path*', + destination: 'http://10.147.20.67:8888/chain/:path*', }, { source: '/socket', - destination: 'https://explorer-test.aelf.io/socket', + destination: 'http://10.147.20.67:8888/socket', }, ]; diff --git a/build/rewrites/production.js b/build/rewrites/production.js index 10751056c..95b73c6ef 100644 --- a/build/rewrites/production.js +++ b/build/rewrites/production.js @@ -1,22 +1,3 @@ -module.exports = [ - { - source: '/api/blockChain', - destination: 'https://explorer-test.aelf.io/chain/api/blockChain', - }, - { - source: '/api/:path*', - destination: 'https://explorer-test.aelf.io/api/:path*', - }, - { - source: '/cms/:path*', - destination: 'https://explorer-test.aelf.io/cms/:path*', - }, - { - source: '/chain/:path*', - destination: 'https://explorer-test.aelf.io/chain/:path*', - }, - { - source: '/socket', - destination: 'https://explorer-test.aelf.io/socket', - }, -]; +// git ignore +const prodRewrites = require('../../baseConfig').prodRewrites; +module.exports = prodRewrites; diff --git a/package.json b/package.json index 83e4f1495..d4f68ea12 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,12 @@ { - "name": "next-demo", + "name": "aelf-block-explorer", "version": "0.1.0", "private": true, "scripts": { - "dev:AELF": "CHAIN_ID='AELF' next dev", - "dev:tDVW": "CHAIN_ID='tDVW' next dev", - "build:AELF": "CHAIN_ID='AELF' next build", - "build:tDVW": "CHAIN_ID='tDVW' next build", - "start:AELF": "CHAIN_ID='AELF' next start", - "start:tDVW": "CHAIN_ID='tDVW' next start", + "dev": "next dev", + "beforeBuild": "node scripts/queryConfig.js", + "build": "next build", + "start": " next start", "lint": "next lint", "dev:analyze": "PORT=4000 ANALYZE=true next dev", "prepare": "husky install" @@ -22,13 +20,13 @@ "@monaco-editor/react": "^4.4.5", "@reduxjs/toolkit": "^1.8.5", "@sentry/apm": "^5.19.0", - "@sentry/node": "^5.19.0", + "@sentry/nextjs": "^7.19.0", "@sentry/react": "^5.19.0", "aelf-block-scan": "^0.4.1", "aelf-bridge": "^0.0.9", "aelf-sdk": "3.2.40", "aelf-sdk-cross-chain": "^1.0.14", - "antd": "4.21.0", + "antd": "^4.23.6", "apisauce": "^0.16.0", "axios": "^0.19.0", "axios-hooks": "^3.1.5", @@ -45,6 +43,7 @@ "eslint-config-prettier": "6.7.0", "eslint-plugin-prettier": "^4.2.1", "file-saver": "^2.0.2", + "firebase": "^9.13.0", "i18next": "^19.0.0", "i18next-browser-languagedetector": "^4.0.1", "ismobilejs": "^1.1.1", @@ -56,6 +55,7 @@ "lodash.throttle": "^4.1.1", "lru-cache": "^7.14.0", "memoize-one": "^5.1.1", + "memory-cache": "^0.2.0", "mobx": "^5.1.1", "mobx-react": "^5.2.8", "mobx-state-tree": "^3.3.0", @@ -125,7 +125,7 @@ "copy-webpack-plugin": "^5.0.5", "cross-env": "^5.2.1", "cssnano": "^4.1.10", - "dotenv": "^8.2.0", + "dotenv": "^16.0.3", "eslint": "^8.23.1", "eslint-config-airbnb": "18.0.1", "eslint-config-airbnb-base": "^14.0.0", diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index ab2fa16a6..000000000 Binary files a/public/favicon.ico and /dev/null differ diff --git a/public/favicon_main.ico b/public/favicon_main.ico new file mode 100644 index 000000000..323f0f372 Binary files /dev/null and b/public/favicon_main.ico differ diff --git a/public/favicon_test.ico b/public/favicon_test.ico new file mode 100644 index 000000000..0760b7940 Binary files /dev/null and b/public/favicon_test.ico differ diff --git a/public/font/Roboto-Bold.ttf b/public/font/Roboto-Bold.ttf deleted file mode 100644 index 91ec21227..000000000 Binary files a/public/font/Roboto-Bold.ttf and /dev/null differ diff --git a/public/font/Roboto-Medium.ttf b/public/font/Roboto-Medium.ttf deleted file mode 100644 index 879834198..000000000 Binary files a/public/font/Roboto-Medium.ttf and /dev/null differ diff --git a/public/font/Roboto-Regular.ttf b/public/font/Roboto-Regular.ttf deleted file mode 100644 index 7d9a6c4c3..000000000 Binary files a/public/font/Roboto-Regular.ttf and /dev/null differ diff --git a/scripts/queryConfig.js b/scripts/queryConfig.js new file mode 100644 index 000000000..146a00f39 --- /dev/null +++ b/scripts/queryConfig.js @@ -0,0 +1,190 @@ +// polyfill +global.location = {}; +const AElf = require('aelf-sdk'); +const fs = require('fs'); +const path = require('path'); +const config = require('../src/constants/config/config.json'); +const mergedConfig = require('../src/constants/config/config.js'); +const axios = require('axios'); +const host = process.argv[process.argv.indexOf('--CHAIN_ENDPOINT') + 1]; +const result = { + ...config, +}; +const aelf = new AElf(new AElf.providers.HttpProvider(host)); +const dotenv = require('dotenv'); +dotenv.config(); + +async function getConfig() { + const wallet = AElf.wallet.getWalletByPrivateKey(mergedConfig.commonPrivateKey); + const { ChainId, GenesisContractAddress } = await aelf.chain.getChainStatus(); + const { CONTRACTS, schemeIds } = config; + result.CHAIN_ID = ChainId; + const zeroContract = await aelf.chain.contractAt(GenesisContractAddress, wallet); + for (const [key, name] of Object.entries(CONTRACTS)) { + const contractAddress = await zeroContract.GetContractAddressByName.call(AElf.utils.sha256(name)); + result[key] = contractAddress; + if (name === 'AElf.ContractNames.Token') { + const contract = await aelf.chain.contractAt(contractAddress, wallet); + const { symbol } = await contract.GetNativeTokenInfo.call(); + let resourceTokens = await contract.GetResourceTokenInfo.call(); + resourceTokens = Array.isArray(resourceTokens.value) + ? resourceTokens.value.map(({ symbol, decimals }) => ({ + symbol, + decimals, + })) + : []; + result.SYMBOL = symbol; + result.resourceTokens = resourceTokens; + } + } + + if (result.electionContractAddr) { + const profit = await aelf.chain.contractAt(result.profitContractAddr, wallet); + const electionSchemeIds = ( + await profit.GetManagingSchemeIds.call({ + manager: result.electionContractAddr, + }) + ).schemeIds; + const treasurySchemaIds = ( + await profit.GetManagingSchemeIds.call({ + manager: result.dividends, + }) + ).schemeIds; + const schemes = [ + electionSchemeIds[1], + electionSchemeIds[0], + treasurySchemaIds[3], + treasurySchemaIds[2], + treasurySchemaIds[4], + ].map((v, i) => ({ + type: schemeIds[i].type, + schemeId: v, + })); + result.schemeIds = schemes; + } + result.genesisContract = GenesisContractAddress; + console.log(result); + const ConfigUrl = 'src/constants/config/config.json'; + fs.writeFileSync(path.resolve(ConfigUrl), `${JSON.stringify(result, null, 2)}\n`); +} + +// enum netWorkType: MAIN | TESTNET +// get cms data +async function getCMS() { + const res = await axios({ + method: 'get', + url: 'https://test-cms.aelf.io/cms/chain-list-by-networks', + params: { + // populate: "chain", + // "filters[netWorkType][$eq]": mergedConfig.NETWORK_TYPE, + netWorkType: mergedConfig.NETWORK_TYPE, + }, + }); + const data = res?.data?.[0] ?? {}; + const ConfigCMSUrl = 'src/constants/config/configCMS.json'; + fs.writeFileSync(path.resolve(ConfigCMSUrl), `${JSON.stringify(data, null, 2)}\n`); +} + +const contractNames = [ + { + name: 'Token', + description: 'contract Token', + contractName: 'AElf.ContractNames.Token', + }, + { + name: 'Dividend', + description: 'contract Dividend', + contractName: 'AElf.ContractNames.Treasury', + }, + { + name: 'Consensus.Dpos', + description: 'contract Consensus', + contractName: 'AElf.ContractNames.Consensus', + }, + { + name: 'Token Converter', + description: 'contract Token Converter', + contractName: 'AElf.ContractNames.TokenConverter', + }, + { + name: 'Election', + description: 'contract Election', + contractName: 'AElf.ContractNames.Election', + }, + { + name: 'Profit', + description: 'contract Profit', + contractName: 'AElf.ContractNames.Profit', + }, + { + name: 'Parliament', + description: 'contract Parliament', + contractName: 'AElf.ContractNames.Parliament', + }, + { + name: 'Association', + description: 'contract Association', + contractName: 'AElf.ContractNames.Association', + }, + { + name: 'Referendum', + description: 'contract Referendum', + contractName: 'AElf.ContractNames.Referendum', + }, + { + name: 'CrossChain', + description: 'contract CrossChain', + contractName: 'AElf.ContractNames.CrossChain', + }, +]; + +async function getContractAddress() { + const wallet = AElf.wallet.createNewWallet(); + const { ChainId, GenesisContractAddress } = await aelf.chain.getChainStatus(); + let result = { + chainId: ChainId, + }; + const zeroContract = await aelf.chain.contractAt(GenesisContractAddress, wallet); + const list = await Promise.all( + contractNames.map(async (item) => { + const { contractName, name, ...left } = item; + try { + const address = await zeroContract.GetContractAddressByName.call(AElf.utils.sha256(contractName)); + return { + ...left, + contractAddress: address, + contractName: name, + }; + } catch (e) { + return { + ...left, + contractAddress: '', + contractName: name, + }; + } + }), + ).then((results) => results.filter((item) => item.contractAddress)); + console.log(list); + result = { + ...result, + contractAddress: [ + { + contractName: 'Genesis', + description: 'contract Genesis', + contractAddress: GenesisContractAddress, + }, + ...list, + ], + }; + const ViewerConfigUrl = 'src/constants/config/viewer/config.json'; + const originResult = JSON.parse(fs.readFileSync(path.resolve(ViewerConfigUrl)).toString()); + result = { + ...originResult, + viewer: { + ...originResult.viewer, + ...result, + }, + }; + fs.writeFileSync(path.resolve(ViewerConfigUrl), `${JSON.stringify(result, null, 2)}\n`); +} +Promise.all([getCMS(), getConfig(), getContractAddress()]).catch(console.error); diff --git a/sentry.client.config.js b/sentry.client.config.js new file mode 100644 index 000000000..9cf65e9a8 --- /dev/null +++ b/sentry.client.config.js @@ -0,0 +1,13 @@ +import * as Sentry from '@sentry/nextjs'; + +const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN; +Sentry.init({ + dsn: SENTRY_DSN, + // We recommend adjusting this value in production, or using tracesSampler + // for finer control + tracesSampleRate: 0.2, + // ... + // Note: if you want to override the automatic release value, do not set a + // `release` value here - use the environment variable `SENTRY_RELEASE`, so + // that it will also get attached to your source maps +}); diff --git a/sentry.server.config.js b/sentry.server.config.js new file mode 100644 index 000000000..9cf65e9a8 --- /dev/null +++ b/sentry.server.config.js @@ -0,0 +1,13 @@ +import * as Sentry from '@sentry/nextjs'; + +const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN; +Sentry.init({ + dsn: SENTRY_DSN, + // We recommend adjusting this value in production, or using tracesSampler + // for finer control + tracesSampleRate: 0.2, + // ... + // Note: if you want to override the automatic release value, do not set a + // `release` value here - use the environment variable `SENTRY_RELEASE`, so + // that it will also get attached to your source maps +}); diff --git a/src/assets/theme/color.less b/src/assets/theme/color.less index 624ce922d..306c3a8ab 100644 --- a/src/assets/theme/color.less +++ b/src/assets/theme/color.less @@ -51,7 +51,7 @@ //@media (min-width: 1200px) { ... }#F7F8F9 // @import '~antd/lib/style/themes/default.less'; -// @import '~antd/dist/antd.less'; +// @import '~antd/dist/antd.css'; // New UI start --- @@ -127,6 +127,7 @@ @fair-pink: #ffeded; @wild-sand: #f5f5f5; @athens-gray: #f7f8fa; +@manatee: #8b92a3; //@borderColor: #d9d9d9; diff --git a/src/assets/theme/customize.less b/src/assets/theme/customize.less index 01c092407..555a4c51f 100644 --- a/src/assets/theme/customize.less +++ b/src/assets/theme/customize.less @@ -1,15 +1,3 @@ -@font-face { - font-family: Roboto-Bold; - src: url('/font/Roboto-Bold.ttf'); -} -@font-face { - font-family: Roboto-Medium; - src: url('/font/Roboto-Medium.ttf'); -} -@font-face { - font-family: Roboto-Regular; - src: url('/font/Roboto-Regular.ttf'); -} html { --@{app-prefix}-primary-color: #4d6aec; --@{app-prefix}-primary-color-hover: #506ef5; diff --git a/src/components/AddressLink/index.tsx b/src/components/AddressLink/index.tsx new file mode 100644 index 000000000..6405ea300 --- /dev/null +++ b/src/components/AddressLink/index.tsx @@ -0,0 +1,36 @@ +/* + * @Author: AbigailDeng Abigail.deng@ienyan.com + * @Date: 2022-10-20 13:39:34 + * @LastEditors: AbigailDeng Abigail.deng@ienyan.com + * @LastEditTime: 2022-10-28 14:36:49 + * @FilePath: /aelf-block-explorer/src/components/AddressLink/index.tsx + * @Description: link to address + */ +import React from 'react'; +import PropTypes from 'prop-types'; +import Link from 'next/link'; +import config from 'constants/viewerApi'; +const AddressLink = (props) => { + const { address, suffix } = props; + + return ( + <> + + {`ELF_${address}_${config.viewer.chainId}`} + + {suffix} + + ); +}; + +AddressLink.propTypes = { + address: PropTypes.string.isRequired, + // eslint-disable-next-line react/forbid-prop-types + suffix: PropTypes.any, +}; + +AddressLink.defaultProps = { + suffix: null, +}; + +export default AddressLink; diff --git a/src/components/Breadcrumb/Breadcrumb.tsx b/src/components/Breadcrumb/Breadcrumb.tsx index 206d5bcf2..4a1d6b617 100644 --- a/src/components/Breadcrumb/Breadcrumb.tsx +++ b/src/components/Breadcrumb/Breadcrumb.tsx @@ -26,7 +26,7 @@ type PathSnippetDto = | 'resourceDetail'; // if you want to hide the Breadcrumb -const NO_BREADCRUMB_PAGES = ['/vote', '/proposal', '/address', '/contract', '/token']; +const NO_BREADCRUMB_PAGES = ['/vote', '/proposal', '/address', '/contracts', '/token']; const noBreadcrumb = (pathname: string) => { const isMainPage = pathname === '/'; return NO_BREADCRUMB_PAGES.filter((item) => pathname.includes(item)).length === 0 && !isMainPage; @@ -55,19 +55,18 @@ const BREADCRUMB_NAME_MAP: { '/vote': 'Vote', '/resource': 'Resource', '/resourceDetail': 'Resource Detail List', - '/contract': 'Contract', + '/contracts': 'Contract', '/proposal': 'Proposal', '/token': 'Token', myvote: 'My Vote', '/search-invalid': '', }; - +// TODO: I don't know why /new-socket can reach here const DO_NOT_DISPLAY_PATH = [ + 'new-socket', '/_error', '/transaction-list', - '/txs', '/unconfirmedTxs', - '/tx/', '/blocks', '/unconfirmedBlocks', ]; @@ -109,6 +108,10 @@ const BREADCRUMB_NAMES_TATE = { url: ['/txs', false], name: [BREADCRUMB_NAME_MAP['/unconfirmedTxs'], BREADCRUMB_NAME_MAP['/unconfirmedTx']], }, + accounts: { + url: ['/txs', false], + name: [BREADCRUMB_NAME_MAP['/txs'], BREADCRUMB_NAME_MAP['/address']], + }, address: { url: ['/txs', false], name: [BREADCRUMB_NAME_MAP['/txs'], BREADCRUMB_NAME_MAP['/address']], @@ -130,8 +133,8 @@ const BREADCRUMB_NAMES_TATE = { name: [BREADCRUMB_NAME_MAP['/resource'], BREADCRUMB_NAME_MAP['/resourceDetail']], }, contract: { - url: ['/contract'], - name: [BREADCRUMB_NAME_MAP['/contract']], + url: ['/contracts'], + name: [BREADCRUMB_NAME_MAP['/contracts']], }, proposal: { url: ['/proposal', false], @@ -163,7 +166,6 @@ class BrowserBreadcrumb extends Component { const current = BREADCRUMB_NAMES_TATE.currentState; const { pathname } = this.props.router; - // hummm, stupid solution const inBlockDetail = current === 'block' && breadcrumbTitle === 'Block List'; const inUnconfirmedBlock = current === 'unconfirmedBlock' && breadcrumbTitle === 'Unconfirmed Block List'; const inTxList = current === 'txs' && breadcrumbTitle === 'Transaction List' && pathname !== '/txs'; @@ -189,7 +191,6 @@ class BrowserBreadcrumb extends Component { return pathname.includes(current); } - // TODO: 如果没有收录,则不展示面包屑。 getExtraBreadcrumbItems(pathSnippets: string[], reloadUrl: string) { return pathSnippets.map((item, index) => { if (index === 0) { @@ -197,10 +198,12 @@ class BrowserBreadcrumb extends Component { } const STATE = BREADCRUMB_NAMES_TATE.states[BREADCRUMB_NAMES_TATE.currentState as PathSnippetDto]; - - if (typeof window !== 'undefined' && !STATE) { - this.props.router.push('/'); - return; + if (!STATE) { + if (typeof window !== 'undefined') { + this.props.router.push('/'); + } + // if don't record url return empty array + return []; } const breadcrumbTitle: string = STATE.name[index] ? STATE.name[index] : BREADCRUMB_NAME_MAP[item]; @@ -265,8 +268,10 @@ class BrowserBreadcrumb extends Component { } render() { - const pathname = this.props.router.asPath; - // I don't know why /new-socket can reach here + const pathname = this.props.router.asPath.split('?')[0]; + // url list doesn't provide '/contract' now + // but if someone add path '/contract' to favourite + // so add '/contract' here for avoiding errors if ( DO_NOT_DISPLAY_PATH.includes(pathname) || pathname.includes('/tx/') || @@ -274,7 +279,11 @@ class BrowserBreadcrumb extends Component { pathname.includes('/block/') || pathname.includes('/search-invalid') || pathname.includes('/search-failed') || - pathname.includes('new-socket') + pathname.includes('/accounts') || + pathname.includes('/contracts') || + pathname.includes('/contract') || + pathname.includes('/token') || + pathname.includes('/viewer') ) { return <>; } @@ -285,7 +294,6 @@ class BrowserBreadcrumb extends Component { const className = noBreadcrumb(pathname) ? 'breadcrumb' : 'breadcrumb hide'; const pathSnippets: string[] = pathname.split('/').filter((i) => i); - const firstBreadcrumbItem = this.getFirstBreadcrumbItem(); const extraBreadcrumbItems = this.getExtraBreadcrumbItems(pathSnippets, reloadUrl); const breadcrumbItems = ([] as JSX.Element[]).concat(firstBreadcrumbItem, extraBreadcrumbItems); diff --git a/src/components/ChainSelect/ChainSelect.styles.less b/src/components/ChainSelect/ChainSelect.styles.less index 2d3cc6887..6645d4908 100644 --- a/src/components/ChainSelect/ChainSelect.styles.less +++ b/src/components/ChainSelect/ChainSelect.styles.less @@ -1,7 +1,7 @@ @import 'assets/theme/color.less'; .chain-select { - width: 164px; + width: 154px; margin-left: 10px; .ant-select-selection-item { color: @mariner !important; diff --git a/src/components/ChainSelect/ChainSelect.js b/src/components/ChainSelect/ChainSelect.tsx similarity index 60% rename from src/components/ChainSelect/ChainSelect.js rename to src/components/ChainSelect/ChainSelect.tsx index 47c236551..8fdbc7900 100644 --- a/src/components/ChainSelect/ChainSelect.js +++ b/src/components/ChainSelect/ChainSelect.tsx @@ -1,21 +1,33 @@ -/** - * @file ToolBar.js - * @author huangzongzhe +/* + * @Author: AbigailDeng Abigail.deng@ienyan.com + * @Date: 2022-10-19 11:19:10 + * @LastEditors: AbigailDeng Abigail.deng@ienyan.com + * @LastEditTime: 2022-10-28 14:53:08 + * @FilePath: /aelf-block-explorer/src/components/ChainSelect/ChainSelect.tsx + * @Description: select main chain and side chain */ -import React, { Component } from 'react'; +import { Component } from 'react'; import { Select } from 'antd'; import config from 'constants/config/config'; require('./ChainSelect.styles.less'); - +interface IChainList { + id: number; + chainId: string; + chainsLinkName: string; + chainsLink: string; +} +interface IProps { + chainList: IChainList[]; +} const { Option } = Select; -export default class ChainSelect extends Component { +export default class ChainSelect extends Component { constructor(props) { super(props); } changeChain(chainId) { - const chainInfo = this.props.chainList.find((item) => item.chainId === chainId); - if (chainInfo.chainsLink) window.location = chainInfo.chainsLink; + const chainInfo = this.props.chainList.find((item) => item.chainId === chainId)!; + if (chainInfo.chainsLink) window.location.href = chainInfo.chainsLink; } renderOptions() { @@ -37,6 +49,7 @@ export default class ChainSelect extends Component { return (
e.stopPropagation()} type="ErrorClose" />} - suffixIcon={} - getPopupContainer={(triggerNode) => triggerNode} - popupClassName={clsx(styles['select-dropdown'], popupClassName)} - className={clsx(styles.select, className)} - {...props} - /> - ); -} diff --git a/src/components/CommonSelect/styles.module.less b/src/components/CommonSelect/styles.module.less deleted file mode 100644 index 8012ff14d..000000000 --- a/src/components/CommonSelect/styles.module.less +++ /dev/null @@ -1,34 +0,0 @@ -@import '/src/assets/theme/color.less'; -// .select { -// :global { -// .@{app-prefix}-select-selector { -// border-radius: 6px !important; -// height: 40px !important; -// .@{app-prefix}-select-selection-item { -// line-height: 38px; -// } -// .@{app-prefix}-select-selection-placeholder, -// .@{app-prefix}-select-selection-search-input { -// height: 40px !important; -// line-height: 38px !important; -// } -// } -// } -// } - -// .select-dropdown { -// :global { -// .@{app-prefix}-select-item { -// min-height: 40px; -// padding: 12px 16px; -// &:hover:not(.@{app-prefix}-select-item-option-selected) { -// background: @bg-3; -// } -// } -// .@{app-prefix}-select-item-option-selected { -// background: @bg-8; -// color: @font-1; -// font-weight: 500; -// } -// } -// } diff --git a/src/components/Container/Container.js b/src/components/Container/Container.js deleted file mode 100644 index 422035a8b..000000000 --- a/src/components/Container/Container.js +++ /dev/null @@ -1,17 +0,0 @@ -import React, { Component } from 'react'; -import { Layout } from 'antd'; - -require('./container.styles.less'); - -const { Content } = Layout; - -export default class Container extends Component { - constructor(props) { - super(props); - } - - render() { - const { children } = this.props; - return {children}; - } -} diff --git a/src/components/Container/Container.tsx b/src/components/Container/Container.tsx new file mode 100644 index 000000000..4e23c3971 --- /dev/null +++ b/src/components/Container/Container.tsx @@ -0,0 +1,25 @@ +/* + * @Author: AbigailDeng Abigail.deng@ienyan.com + * @Date: 2022-09-29 10:12:13 + * @LastEditors: AbigailDeng Abigail.deng@ienyan.com + * @LastEditTime: 2022-10-28 14:57:56 + * @FilePath: /aelf-block-explorer/src/components/Container/Container.tsx + * @Description: container for children components + */ + +import React, { Component, PropsWithChildren } from 'react'; +import { Layout } from 'antd'; +require('./container.styles.less'); + +const { Content } = Layout; + +export default class Container extends Component { + constructor(props) { + super(props); + } + + render() { + const { children } = this.props; + return {children}; + } +} diff --git a/src/components/Copy/index.tsx b/src/components/Copy/index.tsx index 6ad74183d..1d132262e 100644 --- a/src/components/Copy/index.tsx +++ b/src/components/Copy/index.tsx @@ -1,3 +1,11 @@ +/* + * @Author: AbigailDeng Abigail.deng@ienyan.com + * @Date: 2022-09-29 10:12:13 + * @LastEditors: AbigailDeng Abigail.deng@ienyan.com + * @LastEditTime: 2022-10-28 14:58:32 + * @FilePath: /aelf-block-explorer/src/components/Copy/index.tsx + * @Description: copy content to clipboard + */ import { useCopyToClipboard } from 'react-use'; import IconFont from 'components/IconFont'; export default function Copy({ diff --git a/src/components/CopyButton/CopyButton.jsx b/src/components/CopyButton/CopyButton.jsx deleted file mode 100644 index 8798fd228..000000000 --- a/src/components/CopyButton/CopyButton.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import copy from 'copy-to-clipboard'; -import { message } from 'antd'; -import IconFont from '../IconFont'; - -export default function CopyButton({ value }) { - const handleCopy = () => { - try { - copy(value); - message.success('Copied!'); - } catch (e) { - message.error('Copy failed, please copy by yourself.'); - } - }; - return ; -} diff --git a/src/components/CopyButton/CopyButton.tsx b/src/components/CopyButton/CopyButton.tsx new file mode 100644 index 000000000..a10d9236c --- /dev/null +++ b/src/components/CopyButton/CopyButton.tsx @@ -0,0 +1,30 @@ +/* + * @Author: AbigailDeng Abigail.deng@ienyan.com + * @Date: 2022-10-24 15:19:08 + * @LastEditors: AbigailDeng Abigail.deng@ienyan.com + * @LastEditTime: 2022-10-28 14:59:32 + * @FilePath: /aelf-block-explorer/src/components/CopyButton/CopyButton.tsx + * @Description: copy button + */ +import React from 'react'; +import copy from 'copy-to-clipboard'; +import { message } from 'antd'; +import IconFont from '../IconFont'; + +export default function CopyButton({ + value = '', + onClick = undefined, +}: { + value?: string; + onClick?: () => void | undefined; +}) { + const handleCopy = () => { + try { + copy(value); + message.success('Copied Successfully'); + } catch (e) { + message.error('Copy failed, please copy by yourself.'); + } + }; + return ; +} diff --git a/src/components/CustomSkeleton/CustomSkeleton.jsx b/src/components/CustomSkeleton/CustomSkeleton.jsx deleted file mode 100644 index 4ab0b8c3b..000000000 --- a/src/components/CustomSkeleton/CustomSkeleton.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import { Skeleton } from 'antd'; -import React from 'react'; - -export default function CustomSkeleton({ children, loading }) { - return ( - - {children} - - ); -} diff --git a/src/components/CustomSkeleton/CustomSkeleton.tsx b/src/components/CustomSkeleton/CustomSkeleton.tsx new file mode 100644 index 000000000..ac7d82361 --- /dev/null +++ b/src/components/CustomSkeleton/CustomSkeleton.tsx @@ -0,0 +1,18 @@ +/* + * @Author: AbigailDeng Abigail.deng@ienyan.com + * @Date: 2022-09-29 17:14:01 + * @LastEditors: AbigailDeng Abigail.deng@ienyan.com + * @LastEditTime: 2022-10-28 15:01:14 + * @FilePath: /aelf-block-explorer/src/components/CustomSkeleton/CustomSkeleton.tsx + * @Description: skeleton and loading + */ +import { Skeleton } from 'antd'; +import React from 'react'; + +export default function CustomSkeleton({ children, loading }) { + return ( + + {children} + + ); +} diff --git a/src/components/DetailHeader/index.jsx b/src/components/DetailHeader/index.jsx deleted file mode 100644 index e98a988ce..000000000 --- a/src/components/DetailHeader/index.jsx +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @file account detail header - * @author atom-yang - */ -import React, { Fragment } from 'react'; -import { Row, Col, Tooltip, Divider } from 'antd'; -import PropTypes from 'prop-types'; -import { QuestionCircleOutlined } from '@ant-design/icons'; - -const HeaderItem = (props) => { - const { tip, name, desc } = props; - return ( - - - {tip ? ( - - - - ) : null} - {name}: - - {desc} - - ); -}; - -HeaderItem.propTypes = { - tip: PropTypes.string, - name: PropTypes.string.isRequired, - desc: PropTypes.node.isRequired, -}; - -HeaderItem.defaultProps = { - tip: '', -}; - -const DetailHeader = (props) => { - const { columns } = props; - return ( -
-

Overview

- - {columns?.map((v) => ( - - - - - ))} -
- ); -}; - -DetailHeader.propTypes = { - columns: PropTypes.arrayOf(PropTypes.shape(HeaderItem.propTypes)).isRequired, -}; - -export default DetailHeader; diff --git a/src/components/DetailHeader/index.less b/src/components/DetailHeader/index.less deleted file mode 100644 index aff1ec2ac..000000000 --- a/src/components/DetailHeader/index.less +++ /dev/null @@ -1,5 +0,0 @@ -.detail-header { - div.ant-typography { - margin-bottom: 0; - } -} diff --git a/src/components/Dividends/index.jsx b/src/components/Dividends/index.tsx similarity index 76% rename from src/components/Dividends/index.jsx rename to src/components/Dividends/index.tsx index 8ffcfbf38..169ffd443 100644 --- a/src/components/Dividends/index.jsx +++ b/src/components/Dividends/index.tsx @@ -1,11 +1,16 @@ -/** - * @file dividend - * @author atom-yang +/* + * @Author: AbigailDeng Abigail.deng@ienyan.com + * @Date: 2022-10-17 16:40:55 + * @LastEditors: AbigailDeng Abigail.deng@ienyan.com + * @LastEditTime: 2022-10-28 15:02:32 + * @FilePath: /aelf-block-explorer/src/components/Dividends/index.tsx + * @Description: dividends */ import React from 'react'; import { Dropdown, Button, Menu } from 'antd'; import { If, Then, Else } from 'react-if'; import { DownOutlined } from '@ant-design/icons'; +import { numberFormatter } from 'utils/formater'; const Dividends = (props) => { const { dividends, defaultSymbol, useButton = true, ...rest } = props; @@ -41,7 +46,7 @@ const Dividends = (props) => {
- {dividends[defaultKey] || 0} {defaultKey} + {numberFormatter(dividends[defaultKey]) || 0} {defaultKey}
diff --git a/src/components/DownloadPlugins/DownloadPlugins.js b/src/components/DownloadPlugins/DownloadPlugins.tsx similarity index 70% rename from src/components/DownloadPlugins/DownloadPlugins.js rename to src/components/DownloadPlugins/DownloadPlugins.tsx index 32106e4e8..0ede8e6b3 100644 --- a/src/components/DownloadPlugins/DownloadPlugins.js +++ b/src/components/DownloadPlugins/DownloadPlugins.tsx @@ -1,13 +1,18 @@ -/** - * @file - * @author zhouminghui yangpeiyang +/* + * @Author: AbigailDeng Abigail.deng@ienyan.com + * @Date: 2022-09-29 17:14:01 + * @LastEditors: AbigailDeng Abigail.deng@ienyan.com + * @LastEditTime: 2022-10-28 15:03:45 + * @FilePath: /aelf-block-explorer/src/components/DownloadPlugins/DownloadPlugins.tsx + * @Description: show `download and install NightElf browser extension` message */ - -import React, { PureComponent } from 'react'; +import React, { CSSProperties, PureComponent } from 'react'; import { Row, Col } from 'antd'; require('./DownloadPlugins.less'); - -export default class DownloadPlugins extends PureComponent { +interface IProps { + style?: CSSProperties; +} +export default class DownloadPlugins extends PureComponent { getDownload() { console.log('下载'); } @@ -16,7 +21,6 @@ export default class DownloadPlugins extends PureComponent { const { style } = this.props; return (
- {/*
为避免每次操作时填写私钥信息,你可以通过插件来使用这些工具(安装插件后仍然显示这些信息,请尝试刷新操作)
*/}
Please download and install NightElf browser extension. Please don’t forget to refresh the page : )
diff --git a/src/components/EventItem/EventItem.styles.less b/src/components/EventItem/EventItem.styles.less new file mode 100644 index 000000000..784c7a62a --- /dev/null +++ b/src/components/EventItem/EventItem.styles.less @@ -0,0 +1,24 @@ +.event-item { + textarea { + color: @scorpion; + margin-bottom: 20px; + background: @athens-gray; + border-radius: 4px; + height: 126px; + padding: 8px 12px; + border: none; + line-height: 22px; + &:disabled { + color: @scorpion; + opacity: 1; + -webkit-text-fill-color: @scorpion; + } + } + button { + width: 104px; + &.ant-btn-text { + width: fit-content; + padding: 0; + } + } +} diff --git a/src/components/EventItem/index.jsx b/src/components/EventItem/index.jsx deleted file mode 100644 index 7eb11dc17..000000000 --- a/src/components/EventItem/index.jsx +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @file event item - * @author atom-yang - */ -import React, { useState } from 'react'; -import { Button, message, Input } from 'antd'; -import PropTypes from 'prop-types'; -import { deserializeLog } from 'utils/utils'; - -const { TextArea } = Input; - -const EventItem = (props) => { - const [result, setResult] = useState({ ...(props || {}) }); - const [hasDecoded, setHasDecoded] = useState(false); - const [loading, setLoading] = useState(false); - function decode() { - setLoading(true); - if (hasDecoded) { - setResult({ - ...(props || {}), - }); - setHasDecoded(false); - setLoading(false); - } else { - deserializeLog(props) - .then((res) => { - if (Object.keys(res).length === 0) { - throw new Error('Decode failed'); - } - setResult(res); - setLoading(false); - setHasDecoded(true); - }) - .catch(() => { - message.error('Decode failed'); - setLoading(false); - }); - } - } - return ( -
-