PluginProbe
Code Snippets / 3.10.1
Code Snippets v3.10.1
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 3.0.1 All 64 releases
code-snippets / js / services / settings / version.ts

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

192 lines 4.9 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 interface AjaxResponse {
13 success?: boolean
14 data?: {
15 message?: string
16 }
17 }
18
19 declare global {
20 interface Window {
21 code_snippets_version_switch?: VersionConfig
22 __code_snippets_i18n?: {
23 selectDifferent: string
24 switching: string
25 processing: string
26 error: string
27 errorSwitch: string
28 refreshing: string
29 refreshed: string
30 }
31 }
32 }
33
34 const i18n = window.__code_snippets_i18n
35
36 const getCurrentVersion = (): string =>
37 (document.querySelector('.current-version')?.textContent ?? '').trim()
38
39 const bindDropdown = (
40 dropdown: HTMLSelectElement,
41 button: HTMLButtonElement | null,
42 currentVersion: string
43 ): void => {
44 const warningNotice = document.getElementById('version-switch-warning')
45
46 dropdown.addEventListener('change', () => {
47 const selectedVersion = dropdown.value
48 if (!button) {
49 return
50 }
51
52 if (!selectedVersion || selectedVersion === currentVersion) {
53 button.disabled = true
54 warningNotice?.classList.add('hidden')
55 } else {
56 button.disabled = false
57 warningNotice?.classList.remove('hidden')
58 }
59 })
60 }
61
62 const SUCCESS_RELOAD_MS = 3000
63
64 const postForm = async (data: Record<string, string>, config: VersionConfig): Promise<AjaxResponse> => {
65 const body = new URLSearchParams()
66 Object.keys(data).forEach(k => body.append(k, data[k]))
67
68 if (!config.ajaxurl) {
69 throw new Error('ajaxurl not defined in config')
70 }
71
72 const resp = await fetch(config.ajaxurl, {
73 method: 'POST',
74 headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
75 body: body.toString(),
76 credentials: 'same-origin'
77 })
78
79 return <AjaxResponse> await resp.json()
80 }
81
82 const bindSwitch = (
83 button: HTMLButtonElement,
84 dropdown: HTMLSelectElement,
85 result: HTMLDivElement,
86 cfg: VersionConfig,
87 currentVersion: string
88 ): void => {
89 button.addEventListener('click', (): void => {
90 void (async (): Promise<void> => {
91 const targetVersion = dropdown.value
92 if (!targetVersion || targetVersion === currentVersion) {
93 result.className = 'notice notice-warning'
94 result.innerHTML = `<p>${i18n?.selectDifferent}</p>`
95 result.style.display = ''
96 return
97 }
98
99 button.disabled = true
100 const originalText = button.textContent ?? ''
101 button.textContent = i18n?.switching ?? ''
102
103 result.className = 'notice notice-info'
104 result.innerHTML = `<p>${i18n?.processing}</p>`
105 result.style.display = ''
106
107 try {
108 const response = await postForm({
109 action: 'code_snippets_switch_version',
110 target_version: targetVersion,
111 nonce: cfg.nonce_switch ?? ''
112 }, cfg)
113
114 if (response.success) {
115 result.className = 'notice notice-success'
116 result.innerHTML = `<p>${response.data?.message ?? ''}</p>`
117 setTimeout(() => window.location.reload(), SUCCESS_RELOAD_MS)
118 return
119 }
120
121 result.className = 'notice notice-error'
122 result.innerHTML = `<p>${response.data?.message ?? i18n?.error}</p>`
123 button.disabled = false
124 button.textContent = originalText
125 } catch (_err) {
126 result.className = 'notice notice-error'
127 result.innerHTML = `<p>${i18n?.errorSwitch}</p>`
128 button.disabled = false
129 button.textContent = originalText
130 }
131 })()
132 })
133 }
134
135 const REFRESH_RELOAD_MS = 1000
136
137 const bindRefresh = (
138 btn: HTMLButtonElement,
139 cfg: VersionConfig
140 ): void => {
141 btn.addEventListener('click', (): void => {
142 void (async (): Promise<void> => {
143 const original = btn.textContent ?? ''
144 btn.disabled = true
145 btn.textContent = i18n?.error ?? ''
146
147 try {
148 await postForm({
149 action: 'code_snippets_refresh_versions',
150 nonce: cfg.nonce_refresh ?? ''
151 }, cfg)
152
153 btn.textContent = i18n?.refreshed ?? ''
154 setTimeout(() => {
155 btn.disabled = false
156 btn.textContent = original
157 window.location.reload()
158 }, REFRESH_RELOAD_MS)
159 } catch {
160 btn.disabled = false
161 btn.textContent = original
162 }
163 })()
164 })
165 }
166
167 export const initVersionSwitch = (): void => {
168 const currentVersion = getCurrentVersion()
169 const config = window.code_snippets_version_switch
170
171 if (!config) {
172 throw Error('version switch config missing')
173 }
174
175 const button = <HTMLButtonElement | null> document.getElementById('switch-version-btn')
176 const dropdown = <HTMLSelectElement | null> document.getElementById('target_version')
177 const result = <HTMLDivElement | null> document.getElementById('version-switch-result')
178 const refreshBtn = <HTMLButtonElement | null> document.getElementById('refresh-versions-btn')
179
180 if (dropdown) {
181 bindDropdown(dropdown, button, currentVersion)
182 }
183
184 if (button && dropdown && result) {
185 bindSwitch(button, dropdown, result, config, currentVersion)
186 }
187
188 if (refreshBtn) {
189 bindRefresh(refreshBtn, config)
190 }
191 }
192