PluginProbe
Code Snippets / 4.0.0-beta.1
Code Snippets v4.0.0-beta.1
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 4.0.0-beta.1, at js/services/settings/version.ts

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