Merge remote-tracking branch 'upstream/develop' into feat/handleTestNotification
This commit is contained in:
commit
845b7692bc
21 files changed
+636
-37
No files matched your search
@@ -0,0 +1,89 @@
|
||||
import axios from 'axios';
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import { URLSearchParams } from 'url';
|
||||
|
||||
// POEditor API information
|
||||
const API_TOKEN = process.env.POEDITOR_API;
|
||||
const PROJECT_ID = process.env.POEDITOR_PROJECT_ID;
|
||||
const LANGUAGES = (process.env.LANGUAGES || 'tr,en').split(',');
|
||||
const EXPORT_FORMAT = process.env.EXPORT_FORMAT || 'key_value_json';
|
||||
|
||||
// POEditor API endpoint
|
||||
const API_URL = 'https://api.poeditor.com/v2';
|
||||
|
||||
// Function to download translations
|
||||
async function downloadTranslations() {
|
||||
try {
|
||||
console.log('Downloading translations from POEditor...');
|
||||
console.log(`Using export format: ${EXPORT_FORMAT}`);
|
||||
|
||||
for (const language of LANGUAGES) {
|
||||
console.log(`Downloading translations for ${language} language...`);
|
||||
|
||||
// Get export URL from POEditor
|
||||
const exportResponse = await axios.post(`${API_URL}/projects/export`,
|
||||
new URLSearchParams({
|
||||
api_token: API_TOKEN,
|
||||
id: PROJECT_ID,
|
||||
language: language,
|
||||
type: EXPORT_FORMAT
|
||||
})
|
||||
);
|
||||
|
||||
if (exportResponse.data.response.status !== 'success') {
|
||||
throw new Error(`Failed to get export URL for ${language} language: ${JSON.stringify(exportResponse.data)}`);
|
||||
}
|
||||
|
||||
const fileUrl = exportResponse.data.result.url;
|
||||
console.log(`Export URL obtained for ${language}`);
|
||||
|
||||
// Download translation file
|
||||
const downloadResponse = await axios.get(fileUrl, { responseType: 'json' });
|
||||
const translations = downloadResponse.data;
|
||||
console.log(`Downloaded translations for ${language}`);
|
||||
|
||||
// Check the format of data returned from POEditor and convert if necessary
|
||||
let formattedTranslations = translations;
|
||||
|
||||
// If data is in array format, convert it to key-value format
|
||||
if (Array.isArray(translations)) {
|
||||
console.log(`Converting array format to key-value format for ${language}`);
|
||||
formattedTranslations = {};
|
||||
translations.forEach(item => {
|
||||
if (item.term && item.definition) {
|
||||
formattedTranslations[item.term] = item.definition;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Save file
|
||||
const outputPath = path.join(process.cwd(), 'temp', `${language}.json`);
|
||||
await fs.writeJson(outputPath, formattedTranslations, { spaces: 2 });
|
||||
|
||||
console.log(`Translations for ${language} language successfully downloaded and saved: ${outputPath}`);
|
||||
}
|
||||
|
||||
console.log('All translations successfully downloaded!');
|
||||
} catch (error) {
|
||||
console.error('An error occurred while downloading translations:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Main function
|
||||
async function main() {
|
||||
try {
|
||||
// Clean temp folder
|
||||
await fs.emptyDir(path.join(process.cwd(), 'temp'));
|
||||
|
||||
// Download translations
|
||||
await downloadTranslations();
|
||||
} catch (error) {
|
||||
console.error('An error occurred during the process:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Run script
|
||||
main();
|
||||
@@ -0,0 +1,64 @@
|
||||
import axios from "axios";
|
||||
import FormData from "form-data";
|
||||
import fs from "fs-extra";
|
||||
|
||||
// POEditor API information
|
||||
const API_TOKEN = process.env.POEDITOR_API;
|
||||
const PROJECT_ID = process.env.POEDITOR_PROJECT_ID;
|
||||
const FILE_PATH = process.env.FILE_PATH;
|
||||
const LANGUAGE = process.env.LANGUAGE;
|
||||
|
||||
// POEditor API endpoint
|
||||
const API_URL = 'https://api.poeditor.com/v2';
|
||||
|
||||
// Function to upload translations
|
||||
async function uploadTranslations() {
|
||||
try {
|
||||
console.log(`Uploading translations for ${LANGUAGE} language from ${FILE_PATH}... test1`);
|
||||
|
||||
// Check if file exists
|
||||
if (!await fs.pathExists(FILE_PATH)) {
|
||||
throw new Error(`File not found: ${FILE_PATH}`);
|
||||
}
|
||||
|
||||
// Read file content
|
||||
const fileContent = await fs.readFile(FILE_PATH, 'utf8');
|
||||
|
||||
// Validate JSON format
|
||||
try {
|
||||
JSON.parse(fileContent);
|
||||
} catch (error) {
|
||||
throw new Error(`Invalid JSON format in ${FILE_PATH}: ${error.message}`);
|
||||
}
|
||||
|
||||
// Create form data for upload
|
||||
const formData = new FormData();
|
||||
formData.append('api_token', API_TOKEN);
|
||||
formData.append('id', PROJECT_ID);
|
||||
formData.append('language', LANGUAGE);
|
||||
formData.append('updating', 'terms_translations');
|
||||
formData.append('file', fs.createReadStream(FILE_PATH));
|
||||
formData.append('overwrite', '1');
|
||||
formData.append('sync_terms', '1');
|
||||
|
||||
// Upload to POEditor
|
||||
const response = await axios.post(`${API_URL}/projects/upload`, formData, {
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
}
|
||||
});
|
||||
|
||||
if (response.data.response.status !== 'success') {
|
||||
throw new Error(`Failed to upload translations: ${JSON.stringify(response.data)}`);
|
||||
}
|
||||
|
||||
console.log(`Successfully uploaded translations for ${LANGUAGE} language.`);
|
||||
console.log(`Statistics: ${JSON.stringify(response.data.result)}`);
|
||||
} catch (error) {
|
||||
console.error('An error occurred while uploading translations:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Run script
|
||||
uploadTranslations();
|
||||
@@ -0,0 +1,69 @@
|
||||
# POEditor Translation Synchronization
|
||||
|
||||
This GitHub Actions workflow automatically downloads translation files from POEditor and integrates them into the project.
|
||||
|
||||
## How It Works
|
||||
|
||||
The workflow can be triggered in two ways:
|
||||
|
||||
1. **Manual Trigger**: You can manually run the "POEditor Translation Synchronization" workflow from the "Actions" tab in the GitHub interface.
|
||||
2. **Automatic Trigger**: The workflow runs automatically every day at midnight (UTC).
|
||||
|
||||
## Required Settings
|
||||
|
||||
For this workflow to function, you need to define the following secrets in your GitHub repository:
|
||||
|
||||
1. `POEDITOR_API_TOKEN`: Your POEditor API token
|
||||
2. `POEDITOR_PROJECT_ID`: Your POEditor project ID
|
||||
|
||||
You can add these secrets in the "Settings > Secrets and variables > Actions" section of your GitHub repository.
|
||||
|
||||
## Manual Execution
|
||||
|
||||
When running the workflow manually, you can specify which languages to download. Languages should be entered as comma-separated values (e.g., `tr,gb,es`).
|
||||
|
||||
If you don't specify any languages, the default languages `tr` and `en` will be downloaded.
|
||||
|
||||
## Output
|
||||
|
||||
When the workflow completes successfully:
|
||||
|
||||
1. Translation files for the specified languages are downloaded from POEditor
|
||||
2. These files are copied to the `src/locales/` directory
|
||||
3. Changes are automatically committed and pushed to the main branch
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If the workflow fails:
|
||||
|
||||
1. Check the GitHub Actions logs
|
||||
2. Make sure your POEditor API token and project ID are correct
|
||||
3. Ensure that the languages you specified exist in your POEditor project
|
||||
|
||||
# POEditor Upload Workflow
|
||||
|
||||
## Summary of Implemented Translation Workflow
|
||||
|
||||
We have successfully created a GitHub Actions workflow that automatically uploads translation files to POEditor when changes are merged to the develop branch. Here's a summary of what we've implemented:
|
||||
### Created Files
|
||||
|
||||
1. .github/scripts/upload-translations.js
|
||||
|
||||
- A Node.js script that handles the upload of translation files to POEditor
|
||||
- Uses the POEditor API to upload JSON translation files
|
||||
- Validates file existence and JSON format before uploading
|
||||
- Provides detailed logging of the upload process
|
||||
|
||||
2. .github/workflows/poeditor-upload-on-merge.yml - A GitHub Actions workflow that triggers when PRs are merged to the develop branch - Only runs when changes are made to files in the src/locales directory - Detects which translation files were changed in the PR - Extracts language codes from filenames (e.g., tr.json → "tr") - Calls the upload script for each changed file
|
||||
### Workflow Process
|
||||
1. When a PR is merged to the develop branch, the workflow checks if any files in src/locales were modified.
|
||||
|
||||
1. If translation files were changed, the workflow:
|
||||
|
||||
- Sets up the necessary Node.js environment
|
||||
- Installs required dependencies
|
||||
- Identifies which specific translation files were changed
|
||||
- For each changed file, extracts the language code and uploads to POEditor
|
||||
- Provides status notifications about the upload process
|
||||
|
||||
This automated workflow ensures that your translations are always in sync between your codebase and POEditor, eliminating the need for manual uploads and reducing the risk of translation inconsistencies.
|
||||
@@ -0,0 +1,92 @@
|
||||
name: POEditor Translation Synchronization
|
||||
|
||||
on:
|
||||
# For manual triggering
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
languages:
|
||||
description: "Languages to synchronize (comma separated, e.g.: tr,en,es)"
|
||||
required: false
|
||||
default: "tr,en"
|
||||
format:
|
||||
description: "Export format (key_value_json or json)"
|
||||
required: false
|
||||
default: "key_value_json"
|
||||
|
||||
# For automatic execution at a specific time (every day at midnight)
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
jobs:
|
||||
sync-translations:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "18"
|
||||
|
||||
- name: Create package.json for scripts
|
||||
run: |
|
||||
mkdir -p .github/scripts
|
||||
cat > .github/scripts/package.json << EOF
|
||||
{
|
||||
"name": "poeditor-scripts",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"axios": "^1.6.0",
|
||||
"fs-extra": "^11.1.1"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
cd .github/scripts
|
||||
npm install
|
||||
|
||||
- name: Download translations from POEditor
|
||||
env:
|
||||
POEDITOR_API: ${{ secrets.POEDITOR_API }}
|
||||
POEDITOR_PROJECT_ID: ${{ secrets.POEDITOR_PROJECT_ID }}
|
||||
LANGUAGES: ${{ github.event.inputs.languages || 'tr,en' }}
|
||||
EXPORT_FORMAT: ${{ github.event.inputs.format || 'key_value_json' }}
|
||||
run: |
|
||||
mkdir -p temp
|
||||
node .github/scripts/download-translations.js
|
||||
|
||||
- name: Verify translation files
|
||||
run: |
|
||||
echo "Verifying translation files..."
|
||||
for file in temp/*.json; do
|
||||
echo "Checking $file"
|
||||
if [ ! -s "$file" ]; then
|
||||
echo "Error: $file is empty or does not exist"
|
||||
exit 1
|
||||
fi
|
||||
# Validate JSON format
|
||||
cat "$file" | jq . > /dev/null || { echo "Error: $file is not valid JSON"; exit 1; }
|
||||
done
|
||||
echo "All translation files are valid"
|
||||
|
||||
- name: Copy translations to project
|
||||
run: |
|
||||
mkdir -p src/locales
|
||||
cp -r temp/* src/locales/
|
||||
echo "Translation files copied to src/locales/"
|
||||
|
||||
- name: Commit changes
|
||||
run: |
|
||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config --local user.name "github-actions[bot]"
|
||||
git add src/locales/*.json
|
||||
git diff --staged --quiet || git commit -m "Translations updated from POEditor"
|
||||
git push
|
||||
@@ -0,0 +1,101 @@
|
||||
name: Upload Translations to POEditor on PR Merge
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
branches:
|
||||
- develop
|
||||
paths:
|
||||
- "src/locales/**"
|
||||
|
||||
jobs:
|
||||
upload-translations:
|
||||
# Only run if the PR was merged (not just closed) or manually triggered
|
||||
if: github.event.pull_request.merged == true
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # Fetch all history to get changed files
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "18"
|
||||
|
||||
- name: Create package.json for scripts
|
||||
run: |
|
||||
mkdir -p .github/scripts
|
||||
cat > .github/scripts/package.json << EOF
|
||||
{
|
||||
"name": "poeditor-scripts",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"axios": "^1.6.0",
|
||||
"fs-extra": "^11.1.1",
|
||||
"form-data": "^4.0.0"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
cd .github/scripts
|
||||
npm install
|
||||
|
||||
- name: Get changed locale files
|
||||
id: changed-files
|
||||
if: github.event_name == 'pull_request'
|
||||
run: |
|
||||
# Get list of changed files in src/locales directory
|
||||
CHANGED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} -- src/locales/*.json)
|
||||
echo "Changed files: $CHANGED_FILES"
|
||||
|
||||
# Create a JSON array of changed files with language codes
|
||||
echo "CHANGED_FILES<<EOF" >> $GITHUB_ENV
|
||||
echo "$CHANGED_FILES" >> $GITHUB_ENV
|
||||
echo "EOF" >> $GITHUB_ENV
|
||||
|
||||
- name: Upload changed translations to POEditor
|
||||
if: env.CHANGED_FILES != ''
|
||||
env:
|
||||
POEDITOR_API: ${{ secrets.POEDITOR_API }}
|
||||
POEDITOR_PROJECT_ID: ${{ secrets.POEDITOR_PROJECT_ID }}
|
||||
run: |
|
||||
# Process each changed file
|
||||
for FILE in $CHANGED_FILES; do
|
||||
if [[ -f "$FILE" ]]; then
|
||||
# Extract language code from filename (e.g., src/locales/en.json -> en)
|
||||
FILENAME=$(basename "$FILE")
|
||||
|
||||
# Special case: map gb.json to en language code
|
||||
if [ "$FILENAME" == "gb.json" ]; then
|
||||
LANG="en"
|
||||
echo "Found gb.json, mapping to language code 'en'"
|
||||
else
|
||||
LANG=$(basename "$FILE" .json)
|
||||
fi
|
||||
|
||||
echo "Processing $FILE for language $LANG"
|
||||
|
||||
# Upload to POEditor
|
||||
LANGUAGE=$LANG FILE_PATH=$FILE node .github/scripts/upload-translations.js
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Notify on success
|
||||
if: success() && env.CHANGED_FILES != ''
|
||||
run: |
|
||||
echo "Successfully uploaded translation files to POEditor."
|
||||
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
|
||||
echo "Manual trigger comment: ${{ github.event.inputs.comment }}"
|
||||
fi
|
||||
|
||||
- name: Notify on no changes
|
||||
if: env.CHANGED_FILES == ''
|
||||
run: |
|
||||
echo "No translation files were found to upload."
|
||||
@@ -128,7 +128,7 @@ const Search = ({
|
||||
<Typography
|
||||
component="span"
|
||||
className="input-error"
|
||||
color={theme.palette.error.contrastText}
|
||||
color={theme.palette.error.main}
|
||||
mt={theme.spacing(2)}
|
||||
sx={{
|
||||
opacity: 0.8,
|
||||
@@ -188,8 +188,8 @@ const Search = ({
|
||||
color: "red",
|
||||
},
|
||||
"& li.MuiAutocomplete-option:hover:not([aria-selected='true'])": {
|
||||
color: theme.palette.primary.main,
|
||||
backgroundColor: theme.palette.primary.contrastTextSecondary,
|
||||
color: theme.palette.secondary.contrastText,
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
},
|
||||
"& .MuiAutocomplete-noOptions": {
|
||||
px: theme.spacing(6),
|
||||
|
||||
@@ -14,7 +14,14 @@ const Link = ({ level, label, url }) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const levelConfig = {
|
||||
primary: {},
|
||||
primary: {
|
||||
color: theme.palette.primary.contrastTextTertiary,
|
||||
sx: {
|
||||
":hover": {
|
||||
color: theme.palette.primary.contrastTextSecondary,
|
||||
},
|
||||
},
|
||||
},
|
||||
secondary: {
|
||||
color: theme.palette.primary.contrastTextSecondary,
|
||||
sx: {
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
} from "@mui/material";
|
||||
import ThemeSwitch from "../ThemeSwitch";
|
||||
import Avatar from "../Avatar";
|
||||
import StarPrompt from "../StarPrompt";
|
||||
import LockSvg from "../../assets/icons/lock.svg?react";
|
||||
import UserSvg from "../../assets/icons/user.svg?react";
|
||||
import TeamSvg from "../../assets/icons/user-two.svg?react";
|
||||
@@ -608,6 +609,8 @@ function Sidebar() {
|
||||
</List>
|
||||
</Box>
|
||||
|
||||
{!collapsed && <StarPrompt />}
|
||||
|
||||
<List
|
||||
component="nav"
|
||||
disablePadding
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
import React from 'react';
|
||||
import { Typography, IconButton, Stack, Box } from '@mui/material';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { setStarPromptOpen } from '../../Features/UI/uiSlice';
|
||||
|
||||
const StarPrompt = ({
|
||||
repoUrl = 'https://github.com/bluewave-labs/checkmate'
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const dispatch = useDispatch();
|
||||
const { t } = useTranslation();
|
||||
const isOpen = useSelector((state) => state.ui?.starPromptOpen ?? true);
|
||||
const mode = useSelector((state) => state.ui.mode);
|
||||
|
||||
const handleClose = () => {
|
||||
dispatch(setStarPromptOpen(false));
|
||||
};
|
||||
|
||||
const handleStarClick = () => {
|
||||
window.open(repoUrl, '_blank');
|
||||
};
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
return (
|
||||
<Stack
|
||||
direction="column"
|
||||
sx={{
|
||||
width: '100%',
|
||||
padding: `${theme.spacing(6)} ${theme.spacing(6)}`,
|
||||
borderTop: `1px solid ${theme.palette.primary.lowContrast}`,
|
||||
borderBottom: `1px solid ${theme.palette.primary.lowContrast}`,
|
||||
borderRadius: 0,
|
||||
gap: theme.spacing(1.5),
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
}}
|
||||
>
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="center" width="100%" pl={theme.spacing(4)}>
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
sx={{
|
||||
color: mode === 'dark' ? theme.palette.primary.contrastText : theme.palette.text.primary,
|
||||
mt: theme.spacing(3)
|
||||
}}
|
||||
>
|
||||
{t('starPromptTitle')}
|
||||
</Typography>
|
||||
<IconButton
|
||||
onClick={handleClose}
|
||||
size="small"
|
||||
sx={{
|
||||
color: theme.palette.text.primary,
|
||||
padding: 0,
|
||||
marginTop: theme.spacing(-5),
|
||||
'&:hover': {
|
||||
backgroundColor: 'transparent',
|
||||
opacity: 0.8
|
||||
},
|
||||
}}
|
||||
>
|
||||
<CloseIcon sx={{ fontSize: '1.25rem' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
|
||||
<Typography
|
||||
variant="body1"
|
||||
sx={{
|
||||
color: theme.palette.text.secondary,
|
||||
fontSize: '0.938rem',
|
||||
lineHeight: 1.5,
|
||||
mb: 1,
|
||||
px: theme.spacing(4)
|
||||
}}
|
||||
>
|
||||
{t('starPromptDescription')}
|
||||
</Typography>
|
||||
|
||||
<Box
|
||||
component="img"
|
||||
src={`https://img.shields.io/github/stars/bluewave-labs/checkmate?label=checkmate&style=social${mode === 'dark' ? '&color=white' : ''}`}
|
||||
alt="GitHub stars"
|
||||
onClick={handleStarClick}
|
||||
sx={{
|
||||
cursor: 'pointer',
|
||||
transform: 'scale(0.65)',
|
||||
transformOrigin: 'left center',
|
||||
'&:hover': {
|
||||
opacity: 0.8
|
||||
},
|
||||
pl: theme.spacing(4),
|
||||
filter: mode === 'dark' ? 'invert(1)' : 'none'
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default StarPrompt;
|
||||
@@ -0,0 +1,51 @@
|
||||
.wallet-adapter-dropdown {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: var(--env-var-spacing-1);
|
||||
}
|
||||
|
||||
.wallet-adapter-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: auto;
|
||||
height: var(--env-var-height-2) !important;
|
||||
font-size: var(--env-var-font-size-medium-plus) !important;
|
||||
font-weight: 500 !important;
|
||||
margin: 0;
|
||||
padding: calc((var(--env-var-height-2) - var(--env-var-font-size-medium-plus) * 1.2) / 2) var(--env-var-spacing-1);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.wallet-adapter-modal-title {
|
||||
font-size: var(--font-size-h5) !important;
|
||||
}
|
||||
|
||||
/* Separator styling */
|
||||
.wallet-adapter-modal-divider {
|
||||
background-color: var(--border-color) !important;
|
||||
margin: var(--spacing-md) 0 !important;
|
||||
}
|
||||
|
||||
/* Responsive fixes */
|
||||
@media (max-width: 1200px) {
|
||||
.wallet-adapter-button {
|
||||
font-size: var(--env-var-font-size-medium) !important;
|
||||
padding: calc((var(--env-var-height-2) - var(--env-var-font-size-medium) * 1.2) / 2)
|
||||
var(--env-var-spacing-1-minus) !important;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.wallet-adapter-modal-wrapper {
|
||||
flex-direction: column !important;
|
||||
}
|
||||
|
||||
.wallet-adapter-modal-divider {
|
||||
margin: var(--spacing-sm) 0 !important;
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
import { WalletModalProvider } from "@solana/wallet-adapter-react-ui";
|
||||
import { clusterApiUrl } from "@solana/web3.js";
|
||||
import PropTypes from "prop-types";
|
||||
import "./index.css";
|
||||
|
||||
// Default styles that can be overridden by your app
|
||||
import "@solana/wallet-adapter-react-ui/styles.css";
|
||||
|
||||
@@ -24,6 +24,7 @@ const initialState = {
|
||||
timezone: "America/Toronto",
|
||||
distributedUptimeEnabled: false,
|
||||
language: "gb",
|
||||
starPromptOpen: true,
|
||||
};
|
||||
|
||||
const uiSlice = createSlice({
|
||||
@@ -55,6 +56,9 @@ const uiSlice = createSlice({
|
||||
setLanguage(state, action) {
|
||||
state.language = action.payload;
|
||||
},
|
||||
setStarPromptOpen: (state, action) => {
|
||||
state.starPromptOpen = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -67,4 +71,5 @@ export const {
|
||||
setTimezone,
|
||||
setDistributedUptimeEnabled,
|
||||
setLanguage,
|
||||
setStarPromptOpen,
|
||||
} = uiSlice.actions;
|
||||
@@ -30,7 +30,6 @@ const StatusHeader = ({ monitor, connectionStatus, elementToCapture }) => {
|
||||
};
|
||||
|
||||
let bgColor = COLOR_MAP[connectionStatus];
|
||||
|
||||
return (
|
||||
<ColContainer backgroundColor={bgColor}>
|
||||
<Stack
|
||||
@@ -61,7 +60,8 @@ const StatusHeader = ({ monitor, connectionStatus, elementToCapture }) => {
|
||||
backgroundColor={theme.palette.successSecondary.lowContrast}
|
||||
color={theme.palette.success.lowContrast}
|
||||
>
|
||||
{t("distributedUptimeDetailsStatusHeaderUptime")} {(monitor.totalUptime * 100).toFixed(2)}%
|
||||
{t("distributedUptimeDetailsStatusHeaderUptime")}{" "}
|
||||
{(monitor.uptimePercentage * 100).toFixed(2)}%
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Typography
|
||||
|
||||
@@ -298,7 +298,7 @@ const Settings = () => {
|
||||
{t("settingsWalletDescription")}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box>
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'flex-start', gap: 2 }}>
|
||||
<Stack
|
||||
direction="row"
|
||||
spacing={2}
|
||||
@@ -401,6 +401,7 @@ const Settings = () => {
|
||||
</ConfigBox>
|
||||
)}
|
||||
|
||||
|
||||
<ConfigBox>
|
||||
<Box>
|
||||
<Typography component="h1">{t("settingsAbout")}</Typography>
|
||||
|
||||
@@ -24,7 +24,6 @@ const PublicStatus = () => {
|
||||
const [isDeleteOpen, setIsDeleteOpen] = useState(false);
|
||||
// Utils
|
||||
const theme = useTheme();
|
||||
const isAdmin = useIsAdmin();
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
@@ -33,7 +32,6 @@ const PublicStatus = () => {
|
||||
const [deleteStatusPage, isDeleting] = useStatusPageDelete(fetchStatusPage, url);
|
||||
|
||||
// Setup
|
||||
const currentPath = location.pathname;
|
||||
let sx = { paddingLeft: theme.spacing(20), paddingRight: theme.spacing(20) };
|
||||
let link = undefined;
|
||||
const isPublic = location.pathname.startsWith("/status/uptime/public");
|
||||
|
||||
@@ -25,7 +25,7 @@ const StatusPagesTable = ({ data }) => {
|
||||
row.type === "distributed"
|
||||
? `/status/distributed/public/${row.url}`
|
||||
: `/status/uptime/public/${row.url}`;
|
||||
navigate(url);
|
||||
window.open(url, "_blank", "noopener,noreferrer")
|
||||
}
|
||||
},
|
||||
render: (row) => {
|
||||
|
||||
@@ -2,18 +2,30 @@ import { useState } from "react";
|
||||
import { useEffect } from "react";
|
||||
import { networkService } from "../../../../main";
|
||||
import { createToast } from "../../../../Utils/toastUtils";
|
||||
export const useChecksFetch = ({ monitorId, dateRange, page, rowsPerPage }) => {
|
||||
export const useChecksFetch = ({
|
||||
monitorId,
|
||||
monitorType,
|
||||
dateRange,
|
||||
page,
|
||||
rowsPerPage,
|
||||
}) => {
|
||||
const [checks, setChecks] = useState(undefined);
|
||||
const [checksCount, setChecksCount] = useState(undefined);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!monitorType) {
|
||||
console.warn("Monitor Type is not provided. Fetching checks will not proceed.");
|
||||
return;
|
||||
}
|
||||
|
||||
const fetchChecks = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await networkService.getChecksByMonitor({
|
||||
monitorId: monitorId,
|
||||
type: monitorType,
|
||||
sortOrder: "desc",
|
||||
limit: null,
|
||||
dateRange: dateRange,
|
||||
@@ -31,7 +43,7 @@ export const useChecksFetch = ({ monitorId, dateRange, page, rowsPerPage }) => {
|
||||
}
|
||||
};
|
||||
fetchChecks();
|
||||
}, [monitorId, dateRange, page, rowsPerPage]);
|
||||
}, [monitorId, monitorType, dateRange, page, rowsPerPage]);
|
||||
|
||||
return [checks, checksCount, isLoading, networkError];
|
||||
};
|
||||
|
||||
@@ -59,8 +59,11 @@ const UptimeDetails = () => {
|
||||
uiTimezone,
|
||||
});
|
||||
|
||||
const monitorType = monitor?.type;
|
||||
|
||||
const [checks, checksCount, checksAreLoading, checksNetworkError] = useChecksFetch({
|
||||
monitorId,
|
||||
monitorType,
|
||||
dateRange,
|
||||
page,
|
||||
rowsPerPage,
|
||||
|
||||
@@ -332,13 +332,13 @@ const baseTheme = (palette) => ({
|
||||
color: palette.error.main,
|
||||
opacity: 0.8,
|
||||
fontSize: "var(--env-var-font-size-medium)",
|
||||
|
||||
marginLeft: 0,
|
||||
},
|
||||
"& .MuiFormHelperText-root.Mui-error": {
|
||||
opacity: 0.8,
|
||||
fontSize: "var(--env-var-font-size-medium)",
|
||||
color: palette.error.main,
|
||||
whiteSpace: 'nowrap',
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
||||
+21
-21
@@ -100,7 +100,7 @@
|
||||
"distributedUptimeDetailsMonitorHeader": "Distributed Uptime Monitoring powered by DePIN",
|
||||
"distributedUptimeDetailsStatusHeaderUptime": "Uptime:",
|
||||
"distributedUptimeDetailsStatusHeaderLastUpdate": "Last updated",
|
||||
|
||||
|
||||
"settingsGeneralSettings": "General settings",
|
||||
"settingsDisplayTimezone": "Display timezone",
|
||||
"settingsDisplayTimezoneDescription": "The timezone of the dashboard you publicly display.",
|
||||
@@ -142,37 +142,37 @@
|
||||
"settingsFailedToAddDemoMonitors": "Failed to add demo monitors",
|
||||
"settingsMonitorsDeleted": "Successfully deleted all monitors",
|
||||
"settingsFailedToDeleteMonitors": "Failed to delete all monitors",
|
||||
|
||||
"starPromptTitle": "Star Checkmate",
|
||||
"starPromptDescription": "See the latest releases and help grow the community on GitHub",
|
||||
"notifications": {
|
||||
"enableNotifications": "Enable {{platform}} notifications",
|
||||
"testNotification": "Test notification",
|
||||
"addOrEditNotifications": "Add or edit notifications",
|
||||
"slack": {
|
||||
"label": "Slack",
|
||||
"description": "To enable Slack notifications, create a Slack app and enable incoming webhooks. After that, simply provide the webhook URL here.",
|
||||
"webhookLabel": "Webhook URL",
|
||||
"webhookPlaceholder": "https://hooks.slack.com/services/..."
|
||||
"label": "Slack",
|
||||
"description": "To enable Slack notifications, create a Slack app and enable incoming webhooks. After that, simply provide the webhook URL here.",
|
||||
"webhookLabel": "Webhook URL",
|
||||
"webhookPlaceholder": "https://hooks.slack.com/services/..."
|
||||
},
|
||||
"discord": {
|
||||
"label": "Discord",
|
||||
"description": "To send data to a Discord channel from Checkmate via Discord notifications using webhooks, you can use Discord's incoming Webhooks feature.",
|
||||
"webhookLabel": "Discord Webhook URL",
|
||||
"webhookPlaceholder": "https://discord.com/api/webhooks/..."
|
||||
"label": "Discord",
|
||||
"description": "To send data to a Discord channel from Checkmate via Discord notifications using webhooks, you can use Discord's incoming Webhooks feature.",
|
||||
"webhookLabel": "Discord Webhook URL",
|
||||
"webhookPlaceholder": "https://discord.com/api/webhooks/..."
|
||||
},
|
||||
"telegram": {
|
||||
"label": "Telegram",
|
||||
"description": "To enable Telegram notifications, create a Telegram bot using BotFather, an official bot for creating and managing Telegram bots. Then, get the API token and chat ID and write them down here.",
|
||||
"tokenLabel": "Your bot token",
|
||||
"tokenPlaceholder": "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11",
|
||||
"chatIdLabel": "Your Chat ID",
|
||||
"chatIdPlaceholder": "-1001234567890"
|
||||
"label": "Telegram",
|
||||
"description": "To enable Telegram notifications, create a Telegram bot using BotFather, an official bot for creating and managing Telegram bots. Then, get the API token and chat ID and write them down here.",
|
||||
"tokenLabel": "Your bot token",
|
||||
"tokenPlaceholder": "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11",
|
||||
"chatIdLabel": "Your Chat ID",
|
||||
"chatIdPlaceholder": "-1001234567890"
|
||||
},
|
||||
"webhook": {
|
||||
"label": "Webhooks",
|
||||
"description": "You can set up a custom webhook to receive notifications when incidents occur.",
|
||||
"urlLabel": "Webhook URL",
|
||||
"urlPlaceholder": "https://your-server.com/webhook"
|
||||
"label": "Webhooks",
|
||||
"description": "You can set up a custom webhook to receive notifications when incidents occur.",
|
||||
"urlLabel": "Webhook URL",
|
||||
"urlPlaceholder": "https://your-server.com/webhook"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+5
-3
@@ -60,7 +60,6 @@
|
||||
"distributedStatusSubHeaderText": "Dünya çapında milyonlarca cihaz tarafından desteklenen sistem performansını küresel bölgeye, ülkeye veya şehre göre görüntüleyin",
|
||||
"distributedRightCatagoryTitle": "Monitör",
|
||||
"distributedRightCatagoryDescription": "Mainnet Beta Kümesi",
|
||||
|
||||
"settingsGeneralSettings": "Genel ayarlar",
|
||||
"settingsDisplayTimezone": "Görüntüleme saat dilimi",
|
||||
"settingsDisplayTimezoneDescription": "Herkese açık olarak görüntülediğiniz kontrol panelinin saat dilimi.",
|
||||
@@ -101,5 +100,8 @@
|
||||
"settingsDemoMonitorsAdded": "Demo monitörler başarıyla eklendi",
|
||||
"settingsFailedToAddDemoMonitors": "Demo monitörler eklenemedi",
|
||||
"settingsMonitorsDeleted": "Tüm monitörler başarıyla silindi",
|
||||
"settingsFailedToDeleteMonitors": "Monitörler silinemedi"
|
||||
}
|
||||
"settingsFailedToDeleteMonitors": "Monitörler silinemedi",
|
||||
"starPromptTitle": "Checkmate yıldızla değerlendirin",
|
||||
"starPromptDescription": "En son sürümleri görün ve GitHub'daki topluluğun büyümesine yardımcı olun",
|
||||
"testLocale": "TEST1311 UPLOAD"
|
||||
}
|
||||
Reference in new issue
Block a user