Skip to content

Commit a0398b8

Browse files
authored
Sync branch [skip ci]
2 parents 6e14992 + 1667e82 commit a0398b8

File tree

10 files changed

+463
-44
lines changed

10 files changed

+463
-44
lines changed

.github/workflows/diff-translations.yml

Lines changed: 20 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,71 +5,48 @@ on:
55
pull_request:
66
types: [opened, edited, synchronize, ready_for_review]
77
branches:
8-
- "development"
9-
- "new/**"
8+
- development
9+
- master
1010

1111
jobs:
1212
translation:
1313
runs-on: ubuntu-latest
1414
steps:
15-
- name: Checkout Ref Base
15+
- name: Checkout Base Branch
1616
uses: actions/checkout@v4
1717
with:
18-
path: neve-head
18+
ref: ${{ github.base_ref }}
19+
path: neve-base
1920
- name: Setup node 16
2021
uses: actions/setup-node@v4
2122
with:
2223
node-version: 16.x
23-
- name: FRESH Makepot BASE
24+
- name: Build POT for Base Branch
2425
run: |
25-
cd neve-head
26+
cd neve-base
2627
ls languages/
2728
composer install --no-dev --prefer-dist --no-progress --no-suggest
2829
yarn install --frozen-lockfile
2930
yarn run build
3031
ls languages/
31-
- name: Checkout Ref Head
32-
uses: actions/checkout@v2
32+
- name: Checkout PR Branch (Head)
33+
uses: actions/checkout@v4
3334
with:
34-
ref: development
35-
path: neve-base
36-
- name: FRESH Makepot HEAD
35+
path: neve-head
36+
- name: Build POT for PR Branch
3737
run: |
38-
cd neve-base
38+
cd neve-head
3939
ls languages/
4040
composer install --no-dev --prefer-dist --no-progress --no-suggest
4141
yarn install --frozen-lockfile
4242
yarn run build
4343
ls languages/
44-
- name: Find Comment
45-
uses: peter-evans/find-comment@v1
46-
id: find_coomment
47-
with:
48-
issue-number: ${{ github.event.pull_request.number }}
49-
comment-author: "pirate-bot"
50-
body-includes: PR has POT difference
51-
- name: Install PODiff
52-
run: |
53-
curl -o podiff.gz ftp://download.gnu.org.ua/pub/releases/podiff/podiff-1.3.tar.gz
54-
tar -xf podiff.gz
55-
cd podiff-1.3
56-
make
57-
mkdir -p $GITHUB_WORKSPACE/bin
58-
mv ./podiff $GITHUB_WORKSPACE/bin
59-
echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH
60-
cd ..
61-
- name: Run Podiff
62-
id: translation_status
63-
run: |
64-
${GITHUB_WORKSPACE}/neve-head/bin/pot-diff.sh ./neve-base/languages/neve.pot ./neve-head/languages/neve.pot $PERCENT_TRESHOLD
65-
- name: Step require review
66-
if: steps.translation_status.outputs.has_pot_diff != 'success'
67-
uses: Automattic/action-required-review@v2
44+
- name: Compare POT files
45+
uses: Codeinwp/action-i18n-string-reviewer@main
6846
with:
69-
requirements: |
70-
- name: Everything else
71-
paths: unmatched
72-
teams:
73-
- "admin-neve"
74-
status: Has translation changes, a review admin-neve team is required
75-
token: ${{ secrets.BOT_TOKEN }}
47+
fail-on-changes: 'true'
48+
openrouter-key: ${{ secrets.OPEN_ROUTER_API_KEY }}
49+
openrouter-model: 'google/gemini-2.5-flash'
50+
base-pot-file: 'neve-base/languages/neve.pot'
51+
target-pot-file: 'neve-head/languages/neve.pot'
52+
github-token: ${{ secrets.BOT_TOKEN }}
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
/* global neveDash */
2+
import { __, sprintf } from '@wordpress/i18n';
3+
import {
4+
NEVE_AVAILABLE_MODULES_ICON_MAP,
5+
NEVE_STORE,
6+
} from '../../utils/constants';
7+
import { ArrowRight, LoaderCircle, LucideSettings } from 'lucide-react';
8+
import Card from '../../Layout/Card';
9+
import { useState } from '@wordpress/element';
10+
import { useDispatch, useSelect } from '@wordpress/data';
11+
import Toggle from '../Common/Toggle';
12+
import { send } from '../../utils/rest';
13+
14+
const Toast = ({ message }) => {
15+
return (
16+
<div className="fixed flex items-center gap-2 z-[99999] top-10 right-5 bg-white text-black text-base font-medium px-4 py-2 rounded shadow border border-solid border-blue-600">
17+
{message}
18+
</div>
19+
);
20+
};
21+
22+
const ModuleToggle = ({
23+
slug,
24+
moduleData,
25+
setMessage,
26+
isActive,
27+
setIsActive,
28+
isInstalled,
29+
setIsInstalled,
30+
}) => {
31+
const [loading, setLoading] = useState(false);
32+
const { changeModuleStatus, setObfxModuleStatus, setToast } =
33+
useDispatch(NEVE_STORE);
34+
const { moduleStatus } = useSelect((select) => {
35+
const { getObfxModuleStatus } = select(NEVE_STORE);
36+
37+
return {
38+
moduleStatus: getObfxModuleStatus(slug) || false,
39+
};
40+
});
41+
42+
const { api } = neveDash;
43+
const { title } = moduleData;
44+
const toastMessage = {
45+
//translators: %s - Plugin name
46+
installing: sprintf(__('Installing %s', 'neve'), 'Orbit Fox Plugin'),
47+
//translators: %s - Plugin name
48+
activating: sprintf(__('Activating %s', 'neve'), 'Orbit Fox Plugin'),
49+
};
50+
51+
const handleToggle = async (value) => {
52+
try {
53+
setLoading(true);
54+
changeModuleStatus(slug, value);
55+
56+
let isPluginActive = true;
57+
// Handle plugin installation or activation
58+
if (!isInstalled) {
59+
setMessage(toastMessage.installing);
60+
isPluginActive = false;
61+
} else if (!isActive) {
62+
setMessage(toastMessage.activating);
63+
isPluginActive = false;
64+
}
65+
66+
if (!isPluginActive) {
67+
await send(api + 'activate-plugin', {
68+
slug: 'themeisle-companion',
69+
}).then((res) => {
70+
if (res.success) {
71+
setIsInstalled(true);
72+
setIsActive(true);
73+
}
74+
});
75+
}
76+
77+
// Fire the send method after install/activate or immediately if both are done
78+
const response = await send(api + 'activate-module', {
79+
slug,
80+
value,
81+
});
82+
83+
setObfxModuleStatus(slug, response.success ? value : !value);
84+
setToast(
85+
response.success
86+
? (value
87+
? __('Module Activated', 'neve')
88+
: __('Module Deactivated.', 'neve')) + ` (${title})`
89+
: response.data
90+
);
91+
} catch (error) {
92+
setToast(
93+
__('Something went wrong while activating the module.', 'neve')
94+
);
95+
} finally {
96+
setLoading(false);
97+
setMessage('');
98+
}
99+
};
100+
101+
return (
102+
<div className="flex gap-2 items-center">
103+
<Toggle
104+
checked={moduleStatus}
105+
onToggle={handleToggle}
106+
disabled={loading}
107+
/>
108+
</div>
109+
);
110+
};
111+
112+
const AvailableModuleCard = ({
113+
moduleData,
114+
slug,
115+
setMessage,
116+
isActive,
117+
setIsActive,
118+
isInstalled,
119+
setIsInstalled,
120+
}) => {
121+
const { title, description } = moduleData;
122+
const CardIcon = NEVE_AVAILABLE_MODULES_ICON_MAP[slug] || LucideSettings;
123+
124+
return (
125+
<Card
126+
icon={<CardIcon size={18} />}
127+
title={title}
128+
className="bg-white p-6 rounded-lg shadow-sm"
129+
afterTitle={
130+
<ModuleToggle
131+
slug={slug}
132+
moduleData={moduleData}
133+
setMessage={setMessage}
134+
isActive={isActive}
135+
setIsActive={setIsActive}
136+
isInstalled={isInstalled}
137+
setIsInstalled={setIsInstalled}
138+
/>
139+
}
140+
id={`module-${slug}`}
141+
>
142+
<p className="text-gray-600 text-sm leading-relaxed">
143+
{description}
144+
</p>
145+
{!isActive ? (
146+
<p className="mt-2 italic text-sm text-gray-500">
147+
{__(
148+
'This feature is part of OrbitFox plugin, built by the Neve team. Enabling the toggle will automatically install and activate the plugin.',
149+
'neve'
150+
)}
151+
</p>
152+
) : (
153+
<a
154+
className="flex mt-2 text-blue-600 gap-2 align-middle"
155+
href="admin.php?page=obfx_companion"
156+
>
157+
{__('Go to Settings to Edit', 'neve')}
158+
<ArrowRight size={18} />
159+
</a>
160+
)}
161+
</Card>
162+
);
163+
};
164+
165+
export default () => {
166+
const [message, setMessage] = useState('');
167+
const [isInstalled, setIsInstalled] = useState(
168+
neveDash.orbitFox.isInstalled
169+
);
170+
const [isActive, setIsActive] = useState(neveDash.orbitFox.isActive);
171+
172+
return (
173+
<>
174+
<div className="mb-6">
175+
<div className="flex items-center justify-between">
176+
<h2 className="text-lg font-semibold">
177+
{__('Available Modules', 'neve')}
178+
</h2>
179+
</div>
180+
<div className="grid xl:grid-cols-2 gap-6">
181+
{Object.entries(neveDash.availableModules).map(
182+
([slug, moduleData]) => (
183+
<AvailableModuleCard
184+
key={slug}
185+
slug={slug}
186+
moduleData={moduleData}
187+
setMessage={setMessage}
188+
isActive={isActive}
189+
setIsActive={setIsActive}
190+
isInstalled={isInstalled}
191+
setIsInstalled={setIsInstalled}
192+
/>
193+
)
194+
)}
195+
</div>
196+
</div>
197+
{message && (
198+
<Toast
199+
message={
200+
<>
201+
<LoaderCircle
202+
size={18}
203+
className="animate-spin text-blue-800"
204+
/>
205+
{message}
206+
</>
207+
}
208+
/>
209+
)}
210+
</>
211+
);
212+
};
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
import AvailableModule from '../AvailableModule';
12
import ModuleGrid from '../ModuleGrid';
23

34
export default () => {
4-
return <ModuleGrid />;
5+
return (
6+
<>
7+
<AvailableModule />
8+
<ModuleGrid />
9+
</>
10+
);
511
};

assets/apps/dashboard/src/store/actions.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,10 @@ export default {
5050
payload: loggerStatus,
5151
};
5252
},
53+
setObfxModuleStatus(slug, value) {
54+
return {
55+
type: 'SET_OBFX_MODULE_STATUS',
56+
payload: { slug, value },
57+
};
58+
},
5359
};

assets/apps/dashboard/src/store/reducer.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const initialState = {
88
currentTab: 'start',
99
license: neveDash.pro ? neveDash.license : {},
1010
notifications: neveDash.notifications || {},
11+
obfxModuleStatus: neveDash.orbitFox?.data?.module_status || {},
1112
};
1213

1314
const hash = getTabHash();
@@ -73,6 +74,16 @@ const reducer = (state = initialState, action) => {
7374
neve_logger_flag: action.payload,
7475
},
7576
};
77+
case 'SET_OBFX_MODULE_STATUS':
78+
return {
79+
...state,
80+
obfxModuleStatus: {
81+
...state.obfxModuleStatus,
82+
[action.payload.slug]: {
83+
active: action.payload.value,
84+
},
85+
},
86+
};
7687
}
7788
return state;
7889
};

assets/apps/dashboard/src/store/selectors.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,15 @@ export default {
2525

2626
return shownNotifications;
2727
},
28+
getObfxModuleStatus: (state, slug) => {
29+
if (!state.obfxModuleStatus) {
30+
return false;
31+
}
32+
33+
if (state.obfxModuleStatus[slug]) {
34+
return state.obfxModuleStatus[slug]?.active || false;
35+
}
36+
37+
return false;
38+
},
2839
};

0 commit comments

Comments
 (0)