mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-06 22:40:14 -05:00
Added new provider to manage settings for admin-x
refs https://github.com/TryGhost/Team/issues/3151 - adds new settings provider that fetches settings for a site and allows saving them - adds new helpers for making admin api calls and fetching setting values
This commit is contained in:
parent
cfbcd6fc1a
commit
5b0eba9b1f
5 changed files with 172 additions and 3 deletions
|
@ -1,6 +1,7 @@
|
|||
import Heading from './admin-x-ds/global/Heading';
|
||||
import Settings from './components/Settings';
|
||||
import Sidebar from './components/Sidebar';
|
||||
import {SettingsProvider} from './components/SettingsProvider';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
|
@ -22,7 +23,9 @@ function App() {
|
|||
<Sidebar />
|
||||
</div>
|
||||
<div className="flex-auto pt-[3vmin] md:pt-[72px]">
|
||||
<Settings />
|
||||
<SettingsProvider>
|
||||
<Settings />
|
||||
</SettingsProvider>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,20 @@
|
|||
import React from 'react';
|
||||
import React, {useContext} from 'react';
|
||||
|
||||
import GeneralSettings from './settings/general/GeneralSettings';
|
||||
import {SettingsContext} from './SettingsProvider';
|
||||
|
||||
const Settings: React.FC = () => {
|
||||
const {settings} = useContext(SettingsContext) || {};
|
||||
|
||||
// Show loader while settings is first fetched
|
||||
if (!settings) {
|
||||
return (
|
||||
<div className="flex h-full flex-col items-center justify-center">
|
||||
<div className="text-center text-2xl font-bold">Loading...</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<GeneralSettings />
|
||||
|
|
62
ghost/admin-x-settings/src/components/SettingsProvider.tsx
Normal file
62
ghost/admin-x-settings/src/components/SettingsProvider.tsx
Normal file
|
@ -0,0 +1,62 @@
|
|||
import React, {createContext, useEffect, useState} from 'react';
|
||||
import {getSettings, updateSettings} from '../utils/api';
|
||||
|
||||
// Define the Setting type
|
||||
export interface ISetting {
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
// Define the Settings Context
|
||||
interface SettingsContextProps {
|
||||
settings: ISetting[] | null;
|
||||
saveSettings: (updatedSettings: ISetting[]) => void;
|
||||
}
|
||||
|
||||
interface SettingsProviderProps {
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
const SettingsContext = createContext < SettingsContextProps | undefined > (undefined);
|
||||
|
||||
// Create a Settings Provider component
|
||||
const SettingsProvider: React.FC<SettingsProviderProps> = ({children}) => {
|
||||
const [settings, setSettings] = useState <ISetting[] | null> (null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchSettings = async (): Promise<void> => {
|
||||
try {
|
||||
// Make an API call to fetch the settings
|
||||
const data = await getSettings();
|
||||
setSettings(data.settings);
|
||||
} catch (error) {
|
||||
// Log error in settings API
|
||||
}
|
||||
};
|
||||
|
||||
// Fetch the initial settings from the API
|
||||
fetchSettings();
|
||||
}, []);
|
||||
|
||||
const saveSettings = async (updatedSettings: ISetting[]): Promise<void> => {
|
||||
try {
|
||||
// Make an API call to save the updated settings
|
||||
const data = await updateSettings(updatedSettings);
|
||||
|
||||
// Update the local state with the new settings
|
||||
setSettings(data.settings);
|
||||
} catch (error) {
|
||||
console.log('Error', error);
|
||||
// Log error in settings API
|
||||
}
|
||||
};
|
||||
|
||||
// Provide the settings and the saveSettings function to the children components
|
||||
return (
|
||||
<SettingsContext.Provider value={{settings, saveSettings}}>
|
||||
{children}
|
||||
</SettingsContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export {SettingsContext, SettingsProvider};
|
61
ghost/admin-x-settings/src/utils/api.tsx
Normal file
61
ghost/admin-x-settings/src/utils/api.tsx
Normal file
|
@ -0,0 +1,61 @@
|
|||
import {getGhostPaths} from './helpers';
|
||||
|
||||
interface IQueryParams {
|
||||
group: string;
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
// Define the Setting type
|
||||
export interface ISetting {
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
// Define the SettingsResponse type
|
||||
export interface ISettingsResponse {
|
||||
meta: any;
|
||||
settings: ISetting[];
|
||||
}
|
||||
|
||||
export async function getSettings() {
|
||||
const {apiRoot} = getGhostPaths();
|
||||
const queryParams: IQueryParams = {group: 'site,theme,private,members,portal,newsletter,email,amp,labs,slack,unsplash,views,firstpromoter,editor,comments,analytics,announcement,pintura'};
|
||||
const queryString = Object.keys(queryParams).map((key) => {
|
||||
return `${key}=${queryParams[key] || ''}`;
|
||||
}).join('&');
|
||||
|
||||
const response = await fetch(`${apiRoot}/settings/?${queryString}`, {
|
||||
headers: {
|
||||
'app-pragma': 'no-cache',
|
||||
'x-ghost-version': '5.47'
|
||||
},
|
||||
method: 'GET',
|
||||
mode: 'cors',
|
||||
credentials: 'include'
|
||||
});
|
||||
const data: ISettingsResponse = await response.json();
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function updateSettings(newSettings: ISetting[]) {
|
||||
const {apiRoot} = getGhostPaths();
|
||||
|
||||
const payload = JSON.stringify({
|
||||
settings: newSettings
|
||||
});
|
||||
|
||||
const response = await fetch(`${apiRoot}/settings/`, {
|
||||
headers: {
|
||||
'app-pragma': 'no-cache',
|
||||
'x-ghost-version': '5.47',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: payload,
|
||||
method: 'PUT',
|
||||
mode: 'cors',
|
||||
credentials: 'include'
|
||||
});
|
||||
|
||||
const data: ISettingsResponse = await response.json();
|
||||
return data;
|
||||
}
|
31
ghost/admin-x-settings/src/utils/helpers.tsx
Normal file
31
ghost/admin-x-settings/src/utils/helpers.tsx
Normal file
|
@ -0,0 +1,31 @@
|
|||
import {ISetting} from '../components/SettingsProvider';
|
||||
|
||||
export interface IGhostPaths {
|
||||
adminRoot: string;
|
||||
assetRoot: string;
|
||||
apiRoot: string;
|
||||
}
|
||||
|
||||
export function getSettingValue(settings: ISetting[] | null | undefined, key: string): string {
|
||||
if (!settings) {
|
||||
return '';
|
||||
}
|
||||
const setting = settings.find(d => d.key === key);
|
||||
return setting ? setting.value : '';
|
||||
}
|
||||
|
||||
export function getGhostPaths(): IGhostPaths {
|
||||
let path = window.location.pathname;
|
||||
let subdir = path.substr(0, path.search('/ghost/'));
|
||||
let adminRoot = `${subdir}/ghost/`;
|
||||
let assetRoot = `${subdir}/ghost/assets/`;
|
||||
let apiRoot = `${subdir}/ghost/api/admin`;
|
||||
return {adminRoot, assetRoot, apiRoot};
|
||||
}
|
||||
|
||||
export function getLocalTime({timeZone}) {
|
||||
const date = new Date();
|
||||
const options = {timeZone: timeZone, hour12: false, hour: 'numeric', minute: 'numeric', second: 'numeric'};
|
||||
const localTime = date.toLocaleString('en-US', options);
|
||||
return localTime;
|
||||
}
|
Loading…
Reference in a new issue