Inserisci il template hbs nell'outlet del plugin sulla pagina -> user-preferences-interface a user-preferences-account

Ciao, quando voglio aggiungere a user-preferences-account in modo che gli utenti possano scegliere se desiderano la modalità scura o la modalità chiara, provo ad aggiungerla usando il codice sottostante e a inserirla lì usando il plugin outlet, il problema è che non viene visualizzata per la selezione, il codice non è funzionale. Puoi consigliarmi come potrei inserirlo lì? è molto importante per me

bene grazie

{{#if showColorSchemeSelector}}
  <fieldset class="control-group color-scheme">
    <legend class="control-label">{{i18n "user.color_scheme"}}</legend>
    <div class="control-subgroup light-color-scheme">
      {{#if showDarkColorSchemeSelector}}
        <div class="instructions">{{i18n "user.color_schemes.regular" }}</div>
      {{/if}}
      <div class="controls">
        {{combo-box
          content=userSelectableColorSchemes
          value=selectedColorSchemeId
          onChange=(action "loadColorScheme")
          options=(hash
            translatedNone=selectedColorSchemeNoneLabel
            autoInsertNoneItem=showColorSchemeNoneItem
          )
        }}
      </div>
    </div>
    {{#if showDarkColorSchemeSelector}}
      <div class="control-subgroup dark-color-scheme">
        <div class="instructions">{{i18n "user.color_schemes.dark" }}</div>
        <div class="controls">
          {{combo-box
            content=userSelectableDarkColorSchemes
            value=selectedDarkColorSchemeId
            onChange=(action "loadDarkColorScheme")}}
        </div>
      </div>

      <div class="instructions">
        {{i18n "user.color_schemes.dark_instructions" }}
      </div>
    {{/if}}

    {{#if previewingColorScheme}}
      {{#if previewingColorScheme}}
        {{d-button action=(action "undoColorSchemePreview") label="user.color_schemes.undo" icon="undo" class="btn-default btn-small undo-preview"}}
      {{/if}}

      <div class="controls color-scheme-checkbox">
        {{preference-checkbox labelKey="user.color_scheme_default_on_all_devices" checked=makeColorSchemeDefault}}
      </div>
    {{/if}}
  </fieldset>
{{/if}}

Voglio incollare questo codice qui in modo che funzioni correttamente

<script type="text/x-handlebars" data-template-name="/connectors/user-preferences-account/terajsok-custom-user-preferences"></script>

Qualcuno sa come fare tali interventi?

Ciao,

Sì, penso che non funzionerà così. Suggerisco di leggere la Developing Discourse Themes & Theme Components.

Se ho capito bene, vuoi spostare questa sezione dalla pagina dell’interfaccia :arrow_down_small:

Alla pagina dell’account qui :arrow_down_small:

1 Mi Piace

Sì, è esattamente quello che voglio fare. Potresti aiutarmi? Ho già letto l’argomento che hai suggerito, ma non mi ha aiutato in questo caso particolare

È possibile spostare TUTTE le preferenze utente in un’unica pagina? Suppongo che funzionasse così nelle versioni precedenti di discourse.

Ho già trattato parte del motivo per cui questo potrebbe non funzionare qui:

Non puoi aspettarti che questo funzioni senza considerare i Controller o il JS dei Componenti.

Spostare solo elementi del template dell’interfaccia tra i percorsi è improbabile che funzioni a meno che tu non ne tenga conto, ad esempio il template potrebbe fare affidamento su:

  • proprietà calcolate
  • azioni
  • dati serializzati
  • ecc
1 Mi Piace

Ciao, faccio parte del team di Juraj,

sì, lo abbiamo già scoperto, anche modificando un plugin esistente per includere la preferenza dell’interfaccia utente. (incluso il template hbs e il controller js). Suppongo che l’unica via d’uscita sia creare una nuova pagina delle preferenze utente in cui includiamo solo le preferenze che vogliamo visualizzare. Come importiamo le funzioni esistenti in modo che funzionino con la nostra pagina delle preferenze personalizzata?

Un outlet di plugin dovrebbe andare bene finché supera il modello richiesto.

all’interno di quell’outlet dovrai duplicare tutti gli elementi JS richiesti dalla sorgente

Ecco un esempio di JS che imposta un Controller all’interno di un outlet di plugin:

Puoi evitare questo modo piuttosto non standard di definire un Controller facendo tutto all’interno di un Component, ad esempio così:

1 Mi Piace

Grazie per la tua risposta. Tuttavia, a questo punto siamo arrivati a questo punto:

<script type="text/x-handlebars" data-template-name="/connectors/user-preferences-account/tg-custom-prefs">

<fieldset class="control-group color-scheme">
    <legend class="control-label">{{i18n "user.color_scheme"}}</legend>
    <div class="control-subgroup light-color-scheme">
      <div class="controls">
        <ComboBox @content={{this.userSelectableColorSchemes}} @value={{this.selectedColorSchemeId}} @onChange={{action "loadColorScheme"}} @options={{hash
            translatedNone=this.selectedColorSchemeNoneLabel
            autoInsertNoneItem=this.showColorSchemeNoneItem
          }} />
      </div>
    </div>
</fieldset>
</script>

è il codice copiato dal template interface.hbs. Non posso inserire alcun JS nello script di questo componente. Dove metto la funzione setupComponent?

Copia la struttura dei file dei plugin collegati (o se utilizzi un componente tema, puoi usare un componente tema di esempio scritto secondo standard aggiornati).

Non utilizzare questi tag script, utilizza una struttura di file javascript corretta, è più professionale (e probabilmente più facile da mantenere).

1 Mi Piace

In pratica ho creato un componente tema con i seguenti file

/about.json
/javascripts/discourse/connectors/user-preferences-account/component-test.hbs
/javascripts/discourse/connectors/user-preferences-account/component-test.js.es6

Ho incollato il codice hbs pertinente nel template e ho copiato tutto il codice javascript dal controller delle preferenze utente - interfaccia. Ottengo lo stesso risultato di quando l’ho incollato direttamente in un tag . Non credo di aver capito cosa intendessi con l’esempio JS che imposta un controller all’interno di un plugin outlet.

Suggerisco di caricare il tuo codice su Github e condividerlo, se possibile.

Presumo che si tratti di un errore di battitura, dovrebbe essere .js o .js.es6

fai un po’ di attenzione alla terminologia, è un Componente Tema o un Plugin.

1 Mi Piace

Sorry, yes I meant js.es6. Yes it’s a theme component.

I don’t have the theme component uploaded on github.

/about.json:

{
  "name": "Component Test",
  "component": true,
  "license_url": null,
  "about_url": null,
  "authors": null,
  "theme_version": null,
  "minimum_discourse_version": null,
  "maximum_discourse_version": null,
  "assets": {
  },
  "color_schemes": {
  },
  "modifiers": {
  },
  "learn_more": "https://meta.discourse.org/t/beginners-guide-to-using-discourse-themes/91966"
}

/javascripts/discourse/connectors/user-preferences-account/component-test.hbs

<fieldset class="control-group color-scheme">
    <legend class="control-label">{{i18n "user.color_scheme"}}</legend>
    <div class="control-subgroup light-color-scheme">
      <div class="controls">
        <ComboBox @content={{this.userSelectableColorSchemes}} @value={{this.selectedColorSchemeId}} @onChange={{action "loadColorScheme"}} @options={{hash
            translatedNone=this.selectedColorSchemeNoneLabel
            autoInsertNoneItem=this.showColorSchemeNoneItem
          }} />
      </div>
    </div>
</fieldset>

/javascripts/discourse/connectors/user-preferences-account/component-test.js.es6

import Controller, { inject as controller } from "@ember/controller";
import Session from "discourse/models/session";
import { setDefaultHomepage } from "discourse/lib/utilities";
import {
  listColorSchemes,
  loadColorSchemeStylesheet,
  updateColorSchemeCookie,
} from "discourse/lib/color-scheme-picker";
import { listThemes, setLocalTheme } from "discourse/lib/theme-selector";
import { not, reads } from "@ember/object/computed";
import I18n from "I18n";
import { computed } from "@ember/object";
import discourseComputed from "discourse-common/utils/decorators";
import { popupAjaxError } from "discourse/lib/ajax-error";
import { reload } from "discourse/helpers/page-reloader";
import { propertyEqual } from "discourse/lib/computed";

const USER_HOMES = {
  1: "latest",
  2: "categories",
  3: "unread",
  4: "new",
  5: "top",
  6: "bookmarks",
  7: "unseen",
};

const TEXT_SIZES = ["smallest", "smaller", "normal", "larger", "largest"];
const TITLE_COUNT_MODES = ["notifications", "contextual"];

export default Controller.extend({
  currentThemeId: -1,
  previewingColorScheme: false,
  selectedDarkColorSchemeId: null,
  preferencesController: controller("preferences"),
  makeColorSchemeDefault: true,
  canPreviewColorScheme: propertyEqual("model.id", "currentUser.id"),

  init() {
    this._super(...arguments);

    this.set("selectedDarkColorSchemeId", this.session.userDarkSchemeId);
  },

  @discourseComputed("makeThemeDefault")
  saveAttrNames(makeThemeDefault) {
    let attrs = [
      "locale",
      "external_links_in_new_tab",
      "dynamic_favicon",
      "enable_quoting",
      "enable_defer",
      "automatically_unpin_topics",
      "allow_private_messages",
      "enable_allowed_pm_users",
      "homepage_id",
      "hide_profile_and_presence",
      "text_size",
      "title_count_mode",
      "skip_new_user_tips",
      "color_scheme_id",
      "dark_scheme_id",
    ];

    if (makeThemeDefault) {
      attrs.push("theme_ids");
    }

    return attrs;
  },

  @discourseComputed()
  availableLocales() {
    return JSON.parse(this.siteSettings.available_locales);
  },

  @discourseComputed
  defaultDarkSchemeId() {
    return this.siteSettings.default_dark_mode_color_scheme_id;
  },

  @discourseComputed
  textSizes() {
    return TEXT_SIZES.map((value) => {
      return { name: I18n.t(`user.text_size.${value}`), value };
    });
  },

  homepageId: computed(
    "model.user_option.homepage_id",
    "userSelectableHome.[]",
    function () {
      return (
        this.model.user_option.homepage_id ||
        this.userSelectableHome.firstObject.value
      );
    }
  ),

  @discourseComputed
  titleCountModes() {
    return TITLE_COUNT_MODES.map((value) => {
      return { name: I18n.t(`user.title_count_mode.${value}`), value };
    });
  },

  @discourseComputed
  userSelectableThemes() {
    return listThemes(this.site);
  },

  @discourseComputed("userSelectableThemes")
  showThemeSelector(themes) {
    return themes && themes.length > 1;
  },

  @discourseComputed("themeId")
  themeIdChanged(themeId) {
    if (this.currentThemeId === -1) {
      this.set("currentThemeId", themeId);
      return false;
    } else {
      return this.currentThemeId !== themeId;
    }
  },

  @discourseComputed
  userSelectableColorSchemes() {
    return listColorSchemes(this.site);
  },

  showColorSchemeSelector: reads("userSelectableColorSchemes.length"),
  selectedColorSchemeNoneLabel: I18n.t(
    "user.color_schemes.default_description"
  ),

  @discourseComputed(
    "userSelectableThemes",
    "userSelectableColorSchemes",
    "themeId"
  )
  currentSchemeCanBeSelected(userThemes, userColorSchemes, themeId) {
    if (!userThemes || !themeId) {
      return false;
    }

    const theme = userThemes.findBy("id", themeId);
    if (!theme) {
      return false;
    }

    return userColorSchemes.findBy("id", theme.color_scheme_id);
  },

  showColorSchemeNoneItem: not("currentSchemeCanBeSelected"),

  @discourseComputed("model.user_option.theme_ids", "themeId")
  showThemeSetDefault(userOptionThemes, selectedTheme) {
    return !userOptionThemes || userOptionThemes[0] !== selectedTheme;
  },

  @discourseComputed("model.user_option.text_size", "textSize")
  showTextSetDefault(userOptionTextSize, selectedTextSize) {
    return userOptionTextSize !== selectedTextSize;
  },

  homeChanged() {
    const siteHome = this.siteSettings.top_menu.split("|")[0].split(",")[0];
    const userHome = USER_HOMES[this.get("model.user_option.homepage_id")];

    setDefaultHomepage(userHome || siteHome);
  },

  @discourseComputed()
  userSelectableHome() {
    let homeValues = {};
    Object.keys(USER_HOMES).forEach((newValue) => {
      const newKey = USER_HOMES[newValue];
      homeValues[newKey] = newValue;
    });

    let result = [];
    this.siteSettings.top_menu.split("|").forEach((m) => {
      let id = homeValues[m];
      if (id) {
        result.push({ name: I18n.t(`filters.${m}.title`), value: Number(id) });
      }
    });
    return result;
  },

  @discourseComputed
  showDarkModeToggle() {
    return this.defaultDarkSchemeId > 0 && !this.showDarkColorSchemeSelector;
  },

  @discourseComputed
  userSelectableDarkColorSchemes() {
    return listColorSchemes(this.site, {
      darkOnly: true,
    });
  },

  @discourseComputed("userSelectableDarkColorSchemes")
  showDarkColorSchemeSelector(darkSchemes) {
    // when a default dark scheme is set
    // dropdown has two items (disable / use site default)
    // but we show a checkbox in that case
    const minToShow = this.defaultDarkSchemeId > 0 ? 2 : 1;
    return darkSchemes && darkSchemes.length > minToShow;
  },

  enableDarkMode: computed({
    set(key, value) {
      return value;
    },
    get() {
      return this.get("model.user_option.dark_scheme_id") === -1 ? false : true;
    },
  }),

  selectedColorSchemeId: computed({
    set(key, value) {
      return value;
    },
    get() {
      if (!this.session.userColorSchemeId) {
        return;
      }

      const theme = this.userSelectableThemes?.findBy("id", this.themeId);

      // we don't want to display the numeric ID of a scheme
      // when it is set by the theme but not marked as user selectable
      if (
        theme?.color_scheme_id === this.session.userColorSchemeId &&
        !this.userSelectableColorSchemes.findBy(
          "id",
          this.session.userColorSchemeId
        )
      ) {
        return;
      } else {
        return this.session.userColorSchemeId;
      }
    },
  }),

  actions: {
    save() {
      this.set("saved", false);
      const makeThemeDefault = this.makeThemeDefault;
      if (makeThemeDefault) {
        this.set("model.user_option.theme_ids", [this.themeId]);
      }

      const makeTextSizeDefault = this.makeTextSizeDefault;
      if (makeTextSizeDefault) {
        this.set("model.user_option.text_size", this.textSize);
      }

      if (!this.showColorSchemeSelector) {
        this.set("model.user_option.color_scheme_id", null);
      } else if (this.makeColorSchemeDefault) {
        this.set(
          "model.user_option.color_scheme_id",
          this.selectedColorSchemeId
        );
      }

      if (this.showDarkModeToggle) {
        this.set(
          "model.user_option.dark_scheme_id",
          this.enableDarkMode ? null : -1
        );
      } else {
        // if chosen dark scheme matches site dark scheme, no need to store
        if (
          this.defaultDarkSchemeId > 0 &&
          this.selectedDarkColorSchemeId === this.defaultDarkSchemeId
        ) {
          this.set("model.user_option.dark_scheme_id", null);
        } else {
          this.set(
            "model.user_option.dark_scheme_id",
            this.selectedDarkColorSchemeId
          );
        }
      }

      return this.model
        .save(this.saveAttrNames)
        .then(() => {
          this.set("saved", true);

          if (makeThemeDefault) {
            setLocalTheme([]);
          } else {
            setLocalTheme(
              [this.themeId],
              this.get("model.user_option.theme_key_seq")
            );
          }
          if (makeTextSizeDefault) {
            this.model.updateTextSizeCookie(null);
          } else {
            this.model.updateTextSizeCookie(this.textSize);
          }

          if (this.makeColorSchemeDefault) {
            updateColorSchemeCookie(null);
            updateColorSchemeCookie(null, { dark: true });
          } else {
            updateColorSchemeCookie(this.selectedColorSchemeId);

            if (
              this.defaultDarkSchemeId > 0 &&
              this.selectedDarkColorSchemeId === this.defaultDarkSchemeId
            ) {
              updateColorSchemeCookie(null, { dark: true });
            } else {
              updateColorSchemeCookie(this.selectedDarkColorSchemeId, {
                dark: true,
              });
            }
          }

          this.homeChanged();

          if (this.themeId !== this.currentThemeId) {
            reload();
          }
        })
        .catch(popupAjaxError);
    },

    selectTextSize(newSize) {
      const classList = document.documentElement.classList;

      TEXT_SIZES.forEach((name) => {
        const className = `text-size-${name}`;
        if (newSize === name) {
          classList.add(className);
        } else {
          classList.remove(className);
        }
      });

      // Force refresh when leaving this screen
      this.session.requiresRefresh = true;
      this.set("textSize", newSize);
    },

    loadColorScheme(colorSchemeId) {
      this.setProperties({
        selectedColorSchemeId: colorSchemeId,
        previewingColorScheme: this.canPreviewColorScheme,
      });

      if (!this.canPreviewColorScheme) {
        return;
      }

      if (colorSchemeId < 0) {
        const defaultTheme = this.userSelectableThemes.findBy(
          "id",
          this.themeId
        );

        if (defaultTheme && defaultTheme.color_scheme_id) {
          colorSchemeId = defaultTheme.color_scheme_id;
        }
      }
      loadColorSchemeStylesheet(colorSchemeId, this.themeId);
      if (this.selectedDarkColorSchemeId === -1) {
        // set this same scheme for dark mode preview when dark scheme is disabled
        loadColorSchemeStylesheet(colorSchemeId, this.themeId, true);
      }
    },

    loadDarkColorScheme(colorSchemeId) {
      this.setProperties({
        selectedDarkColorSchemeId: colorSchemeId,
        previewingColorScheme: this.canPreviewColorScheme,
      });

      if (!this.canPreviewColorScheme) {
        return;
      }

      if (colorSchemeId === -1) {
        // load preview of regular scheme when dark scheme is disabled
        loadColorSchemeStylesheet(
          this.selectedColorSchemeId,
          this.themeId,
          true
        );
        Session.currentProp("darkModeAvailable", false);
      } else {
        loadColorSchemeStylesheet(colorSchemeId, this.themeId, true);
        Session.currentProp("darkModeAvailable", true);
      }
    },

    undoColorSchemePreview() {
      this.setProperties({
        selectedColorSchemeId: this.session.userColorSchemeId,
        selectedDarkColorSchemeId: this.session.userDarkSchemeId,
        previewingColorScheme: false,
      });
      const darkStylesheet = document.querySelector("link#cs-preview-dark"),
        lightStylesheet = document.querySelector("link#cs-preview-light");
      if (darkStylesheet) {
        darkStylesheet.remove();
      }

      if (lightStylesheet) {
        lightStylesheet.remove();
      }
    },
  },
});

This is all I have, directly copied from the original files.

La prima cosa da controllare: ci sono errori nella console?

Amico mio, “copiare direttamente” probabilmente non funzionerà in molti casi. Devi capire cosa stai facendo e farlo.

export default Controller.extend({

Questo è un esempio lampante. Probabilmente non funzionerà in questo particolare contesto.

Come ho suggerito, per favore guarda il codice di esempio che ho condiviso.

questo è più simile a ciò di cui hai bisogno:

export default {
  setupComponent(args, component) {

perché è un connettore

1 Mi Piace

Grazie per il tuo aiuto. No, non vedo errori nella console ed è la prima cosa che controllo sempre, dato che posso vedere cosa manca nel codice lì.

Ho sostituito il javascript con solo le due funzioni che mi hai inviato, ma non so cosa prendere dall’esempio che mi hai fornito. Come ho detto, non sono sicuro di cosa implementare dato che non vedo errori nella console.