ypankovych commented on issue #18938:
URL: https://github.com/apache/superset/issues/18938#issuecomment-1161789831

   We actually managed to do that with a bunch of tweaks & hacks. 
   
   First of all, you'll need a custom `/static` view to catch the static that's 
being accessed.
   
   ```python
   def custom_static(self, filename):  # vendored from flask and modified to 
support our static files
       # Ensure get_send_file_max_age is called in all cases.
       # Here, we ensure get_send_file_max_age is called for Blueprints.
       cache_timeout = self.get_send_file_max_age(filename)
       with contextlib.suppress(NotFound):
           # here you mutate static files
           mutated, render, mutated_filename = 
get_mutated_static(self.static_folder, filename)
           response = send_from_directory(
               self.static_folder, mutated_filename, cache_timeout=0 if mutated 
else cache_timeout
           )
           if mutated:
               os.remove(os.path.join(self.static_folder, mutated_filename))
           return response
       raise NotFound
   ```
   Then you set it as current static views in your `flask_app_mutator` function:
   ```python
   app.view_functions["static"] = MethodType(custom_static, app)  # hack
   ```
   Here's the `mutated_static`:
   ```python
   def get_mutated_static(static_dir, filename):
       file_path = os.path.join(static_dir, filename)
       for mutator_spec in MUTATED_STATIC:
           if static_dir in mutator_spec.static_dirs and 
mutator_spec.predicate(file_path):
               file_content = mutator_spec.mutator(file_path)
               break
       else:
           return False, False, filename
       _, suffix = os.path.splitext(filename)
       with tempfile.NamedTemporaryFile(dir=static_dir, mode="w", delete=False, 
suffix=suffix) as temp_fp:
           temp_fp.write(file_content)
       return True, mutator_spec.render, os.path.relpath(temp_fp.name, 
static_dir)
   ```
   In a nutshell, you mutate your static, write it to a temp file, make a 
response based on a temp file, you remove the temp file.
   
   Here we register our mutated static:
   ```python
   class MutatedStaticSpec(NamedTuple):
       predicate: Callable[[str], bool]
       mutator: Callable[[str], Union[str, bytes]]
       static_dirs: List[str] = ["default dir here (the superset's one)"]
   
   # mutate static file at runtime
   # you match the file in `predicate` within the `static_dirs` folders, mutate 
the content in `mutator`,
   MUTATED_STATIC = (
       MutatedStaticSpec(
           predicate=lambda file_path: (
               # we don't know the exact filename, as it may change any time
               file_path.endswith(".js")
               and any(placeholder in open(file_path).read() for placeholder in 
JS_CURRENCY_LOCALE_PLACEHOLDERS)
           ),
           mutator=_set_currency_placeholder,
           static_dirs=[os.path.join("/app/superset", "static")],
       ),
   )
   ```
   Here's js currency locale placeholder (you don't need to change it):
   ```python
   # [0] minimized js version, [1] formatted (we need this for compatibility 
between superset 1.4 and 1.5)
   JS_CURRENCY_LOCALE_PLACEHOLDERS = ("currency:[\"$\",\"\"]", "currency: 
[\"$\", \"\"]")
   ```
   And here's `_set_currency_placeholder`:
   ```python
   def _set_currency_placeholder(file_path):
       with open(file_path) as fp:
           file_content = fp.read()
           for placeholder in JS_CURRENCY_LOCALE_PLACEHOLDERS:
               file_content = file_content.replace(
                   placeholder,
                   render_template_string("currency:[\"{{ currency_symbol 
}}\",\"\"]")
               )
       return file_content
   ```
   As you can see here, we render a single string 
`render_template_string("currency:[\"{{ currency_symbol }}\",\"\"]")`, so we 
need to have a currency in our general app context. And as we're using the 
flask app, we can simply add to the global context as follows:
   ```python
   def get_currency():
       # use any currency symbol here, you'd probably want to get it somewhere 
from the settings
       return {"currency_symbol": "$"}
   ```
   Then register that context processor in `superset_config.py` as follows:
   ```python
   CONTEXT_PROCESSORS = (get_client_currency,)
   ```
   
   When you access a chart/dashboard, static will mutate during that process, 
so the currency symbol gets replaced, and you'll see it in the UI.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to