CRUD on instance colors. renders in UI.

This commit is contained in:
ppom 2024-03-04 12:00:00 +01:00
parent a25a7a571a
commit 786225b7bc
14 changed files with 83 additions and 33 deletions

View File

@ -267,7 +267,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Admin do
context: %{current_user: %User{role: role}} context: %{current_user: %User{role: role}}
}) })
when is_admin(role) do when is_admin(role) do
with {:ok, res} <- Admin.save_settings("instance", IO.inspect(args, label: "SAVE_ARGS")), with {:ok, res} <- Admin.save_settings("instance", args),
res <- res <-
res res
|> Enum.map(fn {key, val} -> |> Enum.map(fn {key, val} ->

View File

@ -39,11 +39,6 @@ defmodule Mobilizon.GraphQL.Resolvers.Config do
{:ok, MediaResolver.transform_media(Config.instance_logo())} {:ok, MediaResolver.transform_media(Config.instance_logo())}
end end
@spec instance_favicon(any(), map(), Absinthe.Resolution.t()) :: {:ok, Media.t()}
def instance_favicon(_parent, _params, _resolution) do
{:ok, MediaResolver.transform_media(Config.instance_favicon())}
end
@spec default_picture(any(), map(), Absinthe.Resolution.t()) :: {:ok, Media.t()} @spec default_picture(any(), map(), Absinthe.Resolution.t()) :: {:ok, Media.t()}
def default_picture(_parent, _params, _resolution) do def default_picture(_parent, _params, _resolution) do
{:ok, MediaResolver.transform_media(Config.default_picture())} {:ok, MediaResolver.transform_media(Config.default_picture())}
@ -117,7 +112,8 @@ defmodule Mobilizon.GraphQL.Resolvers.Config do
slogan: Config.instance_slogan(), slogan: Config.instance_slogan(),
languages: Config.instance_languages(), languages: Config.instance_languages(),
instance_logo: Config.instance_logo(), instance_logo: Config.instance_logo(),
instance_favicon: Config.instance_favicon(), primary_color: Config.primary_color(),
secondary_color: Config.secondary_color(),
default_picture: Config.default_picture(), default_picture: Config.default_picture(),
anonymous: %{ anonymous: %{
participation: %{ participation: %{

View File

@ -137,6 +137,9 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
resolve: &Admin.get_default_picture/3 resolve: &Admin.get_default_picture/3
) )
field(:primary_color, :string, description: "The instance's primary color")
field(:secondary_color, :string, description: "The instance's secondary color")
field(:instance_privacy_policy, :string, field(:instance_privacy_policy, :string,
description: "The instance's privacy policy body text" description: "The instance's privacy policy body text"
) )
@ -439,6 +442,9 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
"The default picture, either as an object or directly the ID of an existing media" "The default picture, either as an object or directly the ID of an existing media"
) )
arg(:primary_color, :string, description: "The instance's primary color")
arg(:secondary_color, :string, description: "The instance's secondary color")
arg(:instance_terms, :string, description: "The instance's terms body text") arg(:instance_terms, :string, description: "The instance's terms body text")
arg(:instance_terms_type, :instance_terms_type, description: "The instance's terms type") arg(:instance_terms_type, :instance_terms_type, description: "The instance's terms type")
arg(:instance_terms_url, :string, description: "The instance's terms URL") arg(:instance_terms_url, :string, description: "The instance's terms URL")

View File

@ -63,14 +63,13 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
resolve(&Config.instance_logo/3) resolve(&Config.instance_logo/3)
end end
field(:instance_favicon, :media, description: "The instance's favicon") do
resolve(&Config.instance_favicon/3)
end
field(:default_picture, :media, description: "The default picture") do field(:default_picture, :media, description: "The default picture") do
resolve(&Config.default_picture/3) resolve(&Config.default_picture/3)
end end
field(:primary_color, :string, description: "The instance's primary color")
field(:secondary_color, :string, description: "The instance's secondary color")
field(:privacy, :privacy, description: "The instance's privacy policy") do field(:privacy, :privacy, description: "The instance's privacy policy") do
arg(:locale, :string, arg(:locale, :string,
default_value: "en", default_value: "en",

View File

@ -181,8 +181,6 @@ defmodule Mobilizon.Admin do
@spec save_settings(String.t(), map()) :: {:ok, any} | {:error, any} @spec save_settings(String.t(), map()) :: {:ok, any} | {:error, any}
def save_settings(group, args) do def save_settings(group, args) do
{medias, values} = Map.split(args, [:instance_logo, :instance_favicon, :default_picture]) {medias, values} = Map.split(args, [:instance_logo, :instance_favicon, :default_picture])
IO.inspect(medias, label: "MEDIAS")
IO.inspect(values, label: "VALUES")
Multi.new() Multi.new()
|> do_save_media_setting(group, medias) |> do_save_media_setting(group, medias)

View File

@ -87,6 +87,12 @@ defmodule Mobilizon.Config do
@spec default_picture :: Media.t() | nil @spec default_picture :: Media.t() | nil
def default_picture, do: config_cached_value( "instance", "default_picture") def default_picture, do: config_cached_value( "instance", "default_picture")
@spec primary_color :: Media.t() | nil
def primary_color, do: config_cached_value( "instance", "primary_color")
@spec secondary_color :: Media.t() | nil
def secondary_color, do: config_cached_value( "instance", "secondary_color")
@spec contact :: String.t() | nil @spec contact :: String.t() | nil
def contact, do: config_cached_value("instance", "contact") def contact, do: config_cached_value("instance", "contact")
@ -440,6 +446,8 @@ defmodule Mobilizon.Config do
instance_slogan: instance_slogan(), instance_slogan: instance_slogan(),
registrations_open: instance_registrations_open?(), registrations_open: instance_registrations_open?(),
contact: contact(), contact: contact(),
primary_color: primary_color(),
secondary_color: secondary_color(),
instance_logo: instance_logo(), instance_logo: instance_logo(),
instance_terms: instance_terms(), instance_terms: instance_terms(),
instance_terms_type: instance_terms_type(), instance_terms_type: instance_terms_type(),

View File

@ -172,12 +172,15 @@ type Config {
"The instance's logo" "The instance's logo"
instanceLogo: Media instanceLogo: Media
"The instance's favicon"
instanceFavicon: Media
"The default picture" "The default picture"
defaultPicture: Media defaultPicture: Media
"The instance's primary color"
primaryColor: String
"The instance's secondary color"
secondaryColor: String
"The instance's contact details" "The instance's contact details"
contact: String contact: String

View File

@ -10,7 +10,7 @@ import {
EVENT_PARTICIPANTS, EVENT_PARTICIPANTS,
FEATURES, FEATURES,
GEOCODING_AUTOCOMPLETE, GEOCODING_AUTOCOMPLETE,
INSTANCE_FAVICON, COLORS,
INSTANCE_LOGO, INSTANCE_LOGO,
LOCATION, LOCATION,
MAPS_TILES, MAPS_TILES,
@ -90,15 +90,18 @@ export function useInstanceLogoUrl() {
return { instanceLogoUrl, error, loading }; return { instanceLogoUrl, error, loading };
} }
export function useInstanceFaviconUrl() { export function useColors() {
const { result, error, loading } = useQuery<{ const { result, error, loading } = useQuery<{
config: Pick<IConfig, "instanceFavicon">; config: Pick<IConfig, "primaryColor" | "secondaryColor">;
}>(INSTANCE_FAVICON); }>(COLORS);
const instanceFaviconUrl = computed( const primaryColor = computed(
() => result.value?.config?.instanceFavicon?.url () => result.value?.config?.primaryColor
); );
return { instanceFaviconUrl, error, loading }; const secondaryColor = computed(
() => result.value?.config?.secondaryColor
);
return { primaryColor, secondaryColor, error, loading };
} }
export function useDefaultPicture() { export function useDefaultPicture() {

View File

@ -210,6 +210,8 @@ export const ADMIN_SETTINGS_FRAGMENT = gql`
url url
name name
} }
primaryColor
secondaryColor
instanceTerms instanceTerms
instanceTermsType instanceTermsType
instanceTermsUrl instanceTermsUrl
@ -241,6 +243,8 @@ export const SAVE_ADMIN_SETTINGS = gql`
$instanceLogo: MediaInput $instanceLogo: MediaInput
$instanceFavicon: MediaInput $instanceFavicon: MediaInput
$defaultPicture: MediaInput $defaultPicture: MediaInput
$primaryColor: String
$secondaryColor: String
$instanceTerms: String $instanceTerms: String
$instanceTermsType: InstanceTermsType $instanceTermsType: InstanceTermsType
$instanceTermsUrl: String $instanceTermsUrl: String
@ -260,6 +264,8 @@ export const SAVE_ADMIN_SETTINGS = gql`
instanceLogo: $instanceLogo instanceLogo: $instanceLogo
instanceFavicon: $instanceFavicon instanceFavicon: $instanceFavicon
defaultPicture: $defaultPicture defaultPicture: $defaultPicture
primaryColor: $primaryColor
secondaryColor: $secondaryColor
instanceTerms: $instanceTerms instanceTerms: $instanceTerms
instanceTermsType: $instanceTermsType instanceTermsType: $instanceTermsType
instanceTermsUrl: $instanceTermsUrl instanceTermsUrl: $instanceTermsUrl

View File

@ -12,12 +12,11 @@ export const CONFIG = gql`
demoMode demoMode
countryCode countryCode
languages languages
primaryColor
secondaryColor
instanceLogo { instanceLogo {
url url
} }
instanceFavicon {
url
}
defaultPicture { defaultPicture {
id id
url url
@ -480,12 +479,11 @@ export const INSTANCE_LOGO = gql`
} }
`; `;
export const INSTANCE_FAVICON = gql` export const COLORS = gql`
query InstanceFavicon { query Colors {
config { config {
instanceFavicon { primaryColor
url secondaryColor
}
} }
} }
`; `;

View File

@ -57,6 +57,15 @@ apolloClient
}) })
.then(({ data: configData }) => { .then(({ data: configData }) => {
instanceName.value = configData.config?.name; instanceName.value = configData.config?.name;
const primaryColor = configData.config?.primaryColor;
if (primaryColor) {
document.documentElement.style.setProperty('--custom-primary', primaryColor);
}
const secondaryColor = configData.config?.secondaryColor;
if (secondaryColor) {
document.documentElement.style.setProperty('--custom-secondary', secondaryColor);
}
}); });
const head = createHead(); const head = createHead();

View File

@ -27,8 +27,9 @@ export interface IAdminSettings {
instanceLongDescription: string; instanceLongDescription: string;
contact: string; contact: string;
instanceLogo: IMedia | null; instanceLogo: IMedia | null;
instanceFavicon: IMedia | null;
defaultPicture: IMedia | null; defaultPicture: IMedia | null;
primaryColor: string;
secondaryColor: string;
instanceTerms: string; instanceTerms: string;
instanceTermsType: InstanceTermsType; instanceTermsType: InstanceTermsType;
instanceTermsUrl: string | null; instanceTermsUrl: string | null;

View File

@ -38,8 +38,9 @@ export interface IConfig {
contact: string; contact: string;
slogan: string; slogan: string;
instanceLogo: { url: string }; instanceLogo: { url: string };
instanceFavicon: { url: string };
defaultPicture: { url: string }; defaultPicture: { url: string };
primaryColor: string;
secondaryColor: string;
registrationsOpen: boolean; registrationsOpen: boolean;
registrationsAllowlist: boolean; registrationsAllowlist: boolean;

View File

@ -94,6 +94,26 @@
:maxSize="maxSize" :maxSize="maxSize"
/> />
</label> </label>
<div class="field flex flex-col">
<label class="" for="primary-color">{{
t("Primary Color")
}}</label>
<o-input
type="color"
v-model="settingsToWrite.primaryColor"
id="primary-color"
/>
</div>
<div class="field flex flex-col">
<label class="" for="secondary-color">{{
t("Secondary Color")
}}</label>
<o-input
type="color"
v-model="settingsToWrite.secondaryColor"
id="secondary-color"
/>
</div>
<o-field :label="t('Allow registrations')"> <o-field :label="t('Allow registrations')">
<o-switch v-model="settingsToWrite.registrationsOpen"> <o-switch v-model="settingsToWrite.registrationsOpen">
<p <p
@ -442,6 +462,8 @@ const defaultAdminSettings: IAdminSettings = {
instanceLogo: null, instanceLogo: null,
instanceFavicon: null, instanceFavicon: null,
defaultPicture: null, defaultPicture: null,
primaryColor: "",
secondaryColor: "",
instanceTerms: "", instanceTerms: "",
instanceTermsType: InstanceTermsType.DEFAULT, instanceTermsType: InstanceTermsType.DEFAULT,
instanceTermsUrl: null, instanceTermsUrl: null,