PluginProbe
Code Snippets / 3.9.6
Code Snippets v3.9.6
4.0.0-beta.2 3.10.2 3.10.1 3.10.0 3.10.0-beta.2 3.10.0-beta.1 4.0.0-beta.1 3.9.6 trunk 2.10.0 2.10.1 2.12.0 2.12.1 2.13.0 2.13.1 2.13.2 2.13.3 2.14.0 2.14.1 2.14.2 2.14.3 2.14.4 2.14.5 2.14.6 3.0.0 All 65 releases
code-snippets / js / services / settings / version.ts

version.ts in Code Snippets 3.9.6, at js/services/settings/version.ts

183 lines 5.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 // Handles version switching UI on the settings screen.
2 // Exported init function so callers can opt-in like other settings modules.
3 // Uses vanilla DOM APIs and the global `code_snippets_version_switch` config
4 // injected by PHP via wp_add_inline_script.
5
6 interface VersionConfig {
7 ajaxurl?: string
8 nonce_switch?: string
9 nonce_refresh?: string
10
11 }
12
13 interface AjaxResponse {
14 success?: boolean
15 data?: {
16 message?: string
17 }
18 }
19
20 declare global {
21 interface Window {
22 code_snippets_version_switch?: VersionConfig
23 __code_snippets_i18n?: Record<string, string>
24 }
25 }
26
27 const el = (id: string): HTMLElement | null => document.getElementById(id)
28
29 const getConfig = (): VersionConfig => {
30 const w = <{ code_snippets_version_switch?: VersionConfig }><unknown>window
31 return w.code_snippets_version_switch ?? {}
32 }
33
34 const getCurrentVersion = (): string => (document.querySelector('.current-version')?.textContent ?? '').trim()
35
36 const getI18n = (key: string, fallback: string): string => window.__code_snippets_i18n?.[key] ?? fallback
37
38 const bindDropdown = (
39 dropdown: HTMLSelectElement,
40 button: HTMLButtonElement | null,
41 currentVersion: string,
42 ): void => {
43 dropdown.addEventListener('change', (): void => {
44 const selectedVersion = dropdown.value
45 if (!button) {
46 return
47 }
48 if (!selectedVersion || selectedVersion === currentVersion) {
49 button.disabled = true
50 const warn = el('version-switch-warning')
51 if (warn) { warn.setAttribute('style', 'display: none;') }
52 } else {
53 button.disabled = false
54 const warn = el('version-switch-warning')
55 if (warn) { warn.setAttribute('style', '') }
56 }
57 })
58 }
59
60 const SUCCESS_RELOAD_MS = 3000
61
62 const postForm = async (data: Record<string, string>, cfg: VersionConfig): Promise<AjaxResponse> => {
63 const body = new URLSearchParams()
64 Object.keys(data).forEach(k => body.append(k, data[k]))
65 const resp = await fetch(cfg.ajaxurl ?? '/wp-admin/admin-ajax.php', {
66 method: 'POST',
67 headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
68 body: body.toString(),
69 credentials: 'same-origin',
70 })
71 const json = <AjaxResponse> await resp.json()
72 return json
73 }
74
75 const bindSwitch = (
76 button: HTMLButtonElement,
77 dropdown: HTMLSelectElement,
78 result: HTMLDivElement,
79 cfg: VersionConfig,
80 currentVersion: string,
81 ): void => {
82 button.addEventListener('click', (): void => {
83 void (async (): Promise<void> => {
84 const targetVersion = dropdown.value
85 if (!targetVersion || targetVersion === currentVersion) {
86 result.className = 'notice notice-warning'
87 result.innerHTML = `<p>${getI18n('selectDifferent', 'Please select a different version to switch to.')}</p>`
88 result.style.display = ''
89 return
90 }
91
92 button.disabled = true
93 const originalText = button.textContent ?? ''
94 button.textContent = getI18n('switching', 'Switching...')
95
96 result.className = 'notice notice-info'
97 result.innerHTML = `<p>${getI18n('processing', 'Processing version switch. Please wait...')}</p>`
98 result.style.display = ''
99
100 try {
101 const response = await postForm({
102 action: 'code_snippets_switch_version',
103 target_version: targetVersion,
104 nonce: cfg.nonce_switch ?? '',
105 }, cfg)
106
107 if (response.success) {
108 result.className = 'notice notice-success'
109 result.innerHTML = `<p>${response.data?.message ?? ''}</p>`
110 setTimeout(() => window.location.reload(), SUCCESS_RELOAD_MS)
111 return
112 }
113
114 result.className = 'notice notice-error'
115 result.innerHTML = `<p>${response.data?.message ?? getI18n('error', 'An error occurred.')}</p>`
116 button.disabled = false
117 button.textContent = originalText
118 } catch (_err) {
119 result.className = 'notice notice-error'
120 result.innerHTML = `<p>${getI18n('errorSwitch', 'An error occurred while switching versions. Please try again.')}</p>`
121 button.disabled = false
122 button.textContent = originalText
123 }
124 })()
125 })
126 }
127
128 const REFRESH_RELOAD_MS = 1000
129
130 const bindRefresh = (
131 btn: HTMLButtonElement,
132 cfg: VersionConfig,
133 ): void => {
134 btn.addEventListener('click', (): void => {
135 void (async (): Promise<void> => {
136 const original = btn.textContent ?? ''
137 btn.disabled = true
138 btn.textContent = getI18n('refreshing', 'Refreshing...')
139
140 try {
141 await postForm({
142 action: 'code_snippets_refresh_versions',
143 nonce: cfg.nonce_refresh ?? '',
144 }, cfg)
145
146 btn.textContent = getI18n('refreshed', 'Refreshed!')
147 setTimeout(() => {
148 btn.disabled = false
149 btn.textContent = original
150 window.location.reload()
151 }, REFRESH_RELOAD_MS)
152 } catch {
153 btn.disabled = false
154 btn.textContent = original
155 }
156 })()
157 })
158 }
159
160 export const initVersionSwitch = (): void => {
161 const cfg = getConfig()
162 const currentVersion = getCurrentVersion()
163
164 const button = <HTMLButtonElement | null> el('switch-version-btn')
165 const dropdown = <HTMLSelectElement | null> el('target_version')
166 const result = <HTMLDivElement | null> el('version-switch-result')
167 const refreshBtn = <HTMLButtonElement | null> el('refresh-versions-btn')
168
169 if (dropdown) {
170 bindDropdown(dropdown, button, currentVersion)
171 }
172
173 if (button && dropdown && result) {
174 bindSwitch(button, dropdown, result, cfg, currentVersion)
175 }
176
177 if (refreshBtn) {
178 bindRefresh(refreshBtn, cfg)
179 }
180 }
181
182
183