mirror of
https://github.com/Lissy93/dashy.git
synced 2024-12-27 19:03:39 +03:00
Merge branch 'master' of github.com:Lissy93/dashy into FEATURE/minimal-view
This commit is contained in:
commit
2b0e17c169
11
.github/CHANGELOG.md
vendored
11
.github/CHANGELOG.md
vendored
@ -1,8 +1,15 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 🌐 1.5.5 - Adds Missing Translations + Small UI Issues [PR #129](https://github.com/Lissy93/dashy/pull/129)
|
||||||
|
- Adds missing translations to several UI elements, Re: #126
|
||||||
|
- Fixes login translations not being picked up on page load, Re: #127
|
||||||
|
- Fixes small text overflow glitch in config icon, Re: #123
|
||||||
|
- Several small UI improvements: height of config editor, scrollbar on theme dropdown, page height, white-on-white on material theme, etc
|
||||||
|
- Adds an action to auto-assign reviewer based on ./.github/CODEOWNERS file
|
||||||
|
|
||||||
## 🐳 1.5.4 - Docker ARM Support [PR #122](https://github.com/Lissy93/dashy/pull/122)
|
## 🐳 1.5.4 - Docker ARM Support [PR #122](https://github.com/Lissy93/dashy/pull/122)
|
||||||
- Adds Docker files for `arm64v8` and `arm32v7` in order to support Raspberry Pi and other modern ARM-based devices
|
- Adds a Dockerfile for `arm64v8` and `arm32v7`, to support Raspberry Pi and other modern ARM-based devices
|
||||||
- Publishes these images on DockerHub and sets up a workflow to submit a new container every time a release is made
|
- Sets up automated workflow to publish ARM containers to DockerHub after every new release
|
||||||
- Adds documentation for running Dashy on RPi/ ARM-based devices, Re: #117
|
- Adds documentation for running Dashy on RPi/ ARM-based devices, Re: #117
|
||||||
|
|
||||||
## 🩹 1.5.3 - UI Quick Fix [PR #121](https://github.com/Lissy93/dashy/pull/121)
|
## 🩹 1.5.3 - UI Quick Fix [PR #121](https://github.com/Lissy93/dashy/pull/121)
|
||||||
|
16
.github/CODEOWNERS
vendored
Normal file
16
.github/CODEOWNERS
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Code Owners helps give greater control to those who developed a feature
|
||||||
|
# PR's which modify files that you own will be marked as trusted
|
||||||
|
# After developing a feature, you can add yourself as it's owner
|
||||||
|
# Each line starts with file pattern, followed by one or more owners
|
||||||
|
# Codeowners Docs: https://github.blog/2017-07-06-introducing-code-owners/
|
||||||
|
|
||||||
|
# Repo Owner
|
||||||
|
* @lissy93
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
src/assets/locales/de.json @niklashere
|
||||||
|
src/assets/locales/nl.json @evroon
|
||||||
|
|
||||||
|
# Bot PR Permissions
|
||||||
|
docs/assets/CONTRIBUTORS.svg @liss-bot
|
||||||
|
docs/*.md @liss-bot
|
@ -1,9 +1,9 @@
|
|||||||
FROM node:lts-alpine
|
FROM node:lts-alpine
|
||||||
|
|
||||||
# Define some ENV Vars
|
# Define some ENV Vars
|
||||||
ENV PORT 80
|
ENV PORT=80 \
|
||||||
ENV DIRECTORY /app
|
DIRECTORY=/app \
|
||||||
ENV IS_DOCKER true
|
IS_DOCKER=true
|
||||||
|
|
||||||
# Create and set the working directory
|
# Create and set the working directory
|
||||||
WORKDIR ${DIRECTORY}
|
WORKDIR ${DIRECTORY}
|
||||||
|
@ -1,31 +1,43 @@
|
|||||||
FROM arm32v7/node:latest
|
FROM alpine:3.12 AS builder
|
||||||
|
|
||||||
# Define some ENV Vars
|
# Download QEMU, see https://github.com/docker/hub-feedback/issues/1261
|
||||||
ENV PORT 80
|
RUN QEMU_URL=https://github.com/balena-io/qemu/releases/download/v5.2.0%2Bbalena4/qemu-5.2.0.balena4-arm.tar.gz \
|
||||||
ENV DIRECTORY /app
|
&& apk add curl && curl -L $QEMU_URL | tar zxvf - -C . --strip-components 1
|
||||||
ENV IS_DOCKER true
|
|
||||||
|
# Start second (arm32v7) stage
|
||||||
# Create and set the working directory
|
FROM arm32v7/alpine:3.12
|
||||||
WORKDIR ${DIRECTORY}
|
|
||||||
|
# Add QEMU from build stage
|
||||||
# Copy over both 'package.json' and 'yarn.lock'
|
COPY --from=builder qemu-arm-static /usr/bin
|
||||||
COPY package.json ./
|
|
||||||
COPY yarn.lock ./
|
# Install Node and Yarn
|
||||||
|
RUN apk add --update --no-cache nodejs npm yarn
|
||||||
# Install dependencies
|
|
||||||
RUN yarn
|
# Define some ENV Vars
|
||||||
|
ENV PORT=80 \
|
||||||
# Copy over all project files and folders to the working directory
|
DIRECTORY=/app \
|
||||||
COPY . .
|
IS_DOCKER=true
|
||||||
|
|
||||||
# Build Dashy for production
|
# Create and set the working directory
|
||||||
RUN yarn build
|
WORKDIR ${DIRECTORY}
|
||||||
|
|
||||||
# Expose users port
|
# Copy over both 'package.json' and 'package-lock.json' (if available)
|
||||||
EXPOSE ${PORT}
|
COPY package*.json ./
|
||||||
|
|
||||||
# Finally, run start command to serve up the built application
|
# Install project dependencies
|
||||||
CMD [ "yarn", "build-and-start"]
|
RUN yarn
|
||||||
|
|
||||||
# Enable Docker healthcecks, to ensure Dashy is running correctly
|
# Copy over all project files and folders to the working directory
|
||||||
HEALTHCHECK --interval=5m --timeout=2s --start-period=30s CMD yarn health-check
|
COPY . .
|
||||||
|
|
||||||
|
# Build initial app for production
|
||||||
|
RUN yarn build
|
||||||
|
|
||||||
|
# Expose given port
|
||||||
|
EXPOSE ${PORT}
|
||||||
|
|
||||||
|
# Finally, run start command to serve up the built application
|
||||||
|
CMD [ "yarn", "build-and-start"]
|
||||||
|
|
||||||
|
# Run simple healthchecks every 5 mins, to check the Dashy's everythings great
|
||||||
|
HEALTHCHECK --interval=5m --timeout=2s --start-period=30s CMD yarn health-check
|
||||||
|
@ -1,16 +1,28 @@
|
|||||||
FROM arm64v8/node:latest
|
FROM alpine:3.12 AS builder
|
||||||
|
|
||||||
|
# Download QEMU, see https://github.com/docker/hub-feedback/issues/1261
|
||||||
|
RUN QEMU_URL=https://github.com/balena-io/qemu/releases/download/v5.2.0%2Bbalena4/qemu-5.2.0.balena4-aarch64.tar.gz \
|
||||||
|
&& apk add curl && curl -L $QEMU_URL | tar zxvf - -C . --strip-components 1
|
||||||
|
|
||||||
|
# Start second (arm64v8) stage
|
||||||
|
FROM arm64v8/alpine:3.12
|
||||||
|
|
||||||
|
# Add QEMU from build stage
|
||||||
|
COPY --from=builder qemu-aarch64-static /usr/bin
|
||||||
|
|
||||||
|
# Install Node and Yarn
|
||||||
|
RUN apk add --update --no-cache nodejs npm yarn
|
||||||
|
|
||||||
# Define some ENV Vars
|
# Define some ENV Vars
|
||||||
ENV PORT 80
|
ENV PORT=80 \
|
||||||
ENV DIRECTORY /app
|
DIRECTORY=/app \
|
||||||
ENV IS_DOCKER true
|
IS_DOCKER=true
|
||||||
|
|
||||||
# Create and set the working directory
|
# Create and set the working directory
|
||||||
WORKDIR ${DIRECTORY}
|
WORKDIR ${DIRECTORY}
|
||||||
|
|
||||||
# Copy over both 'package.json' and 'package-lock.json' (if available)
|
# Copy over both 'package.json' and 'package-lock.json' (if available)
|
||||||
COPY package.json ./
|
COPY package*.json ./
|
||||||
COPY yarn.lock ./
|
|
||||||
|
|
||||||
# Install project dependencies
|
# Install project dependencies
|
||||||
RUN yarn
|
RUN yarn
|
||||||
|
@ -350,6 +350,7 @@ Dashy has the ability to support multiple languages and locales. When available,
|
|||||||
- 🇬🇧 **English**: `en`
|
- 🇬🇧 **English**: `en`
|
||||||
- 🇩🇪 **German**: `de`
|
- 🇩🇪 **German**: `de`
|
||||||
- 🇳🇱 **Dutch**: `nl`
|
- 🇳🇱 **Dutch**: `nl`
|
||||||
|
- 🇲🇫 **French**: `fr`
|
||||||
|
|
||||||
#### Add your Language
|
#### Add your Language
|
||||||
It would be awesome for open source projects to be available to everyone, without language being a barrier to entry for non-native English speakers. If you have a few minutes to sapir, you're help with translating it would be very much appreciated.
|
It would be awesome for open source projects to be available to everyone, without language being a barrier to entry for non-native English speakers. If you have a few minutes to sapir, you're help with translating it would be very much appreciated.
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<a href="https://github.com/swcarlosrj">
|
<a href="https://github.com/swcarlosrj">
|
||||||
<img src="https://avatars.githubusercontent.com/u/9881700?v=4" width="80;" alt="swcarlosrj"/>
|
<img src="https://avatars.githubusercontent.com/u/9881700?u=c92e4a0ccc0bff241e50582bce914b179b6d89b6&v=4" width="80;" alt="swcarlosrj"/>
|
||||||
<br />
|
<br />
|
||||||
<sub><b>Carlos Rufo</b></sub>
|
<sub><b>Carlos Rufo</b></sub>
|
||||||
</a>
|
</a>
|
||||||
@ -71,7 +71,7 @@
|
|||||||
<!-- readme: contributors -end -->
|
<!-- readme: contributors -end -->
|
||||||
|
|
||||||
## Helpful Users
|
## Helpful Users
|
||||||
<!-- readme: EVOTk,shadowking001,turnrye,Robert-Ernst,MilesTEG1,Niklashere -start -->
|
<!-- readme: EVOTk,shadowking001,turnrye,Robert-Ernst,Niklashere,evroon,MilesTEG1 -start -->
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
@ -152,7 +152,7 @@
|
|||||||
This app definitely wouldn't have been quite so possible without the making use of the following package and components. Full credit and big kudos to their respective authors, who've done an amazing job in building and maintaining them. For a full breakdown of dependency licenses, please see [Legal](https://github.com/Lissy93/dashy/blob/master/.github/LEGAL.md)
|
This app definitely wouldn't have been quite so possible without the making use of the following package and components. Full credit and big kudos to their respective authors, who've done an amazing job in building and maintaining them. For a full breakdown of dependency licenses, please see [Legal](https://github.com/Lissy93/dashy/blob/master/.github/LEGAL.md)
|
||||||
|
|
||||||
##### Core
|
##### Core
|
||||||
At it's core, the application uses [Vue.js](https://github.com/vuejs/vue), as well as it's services. Styling is done with [SCSS](https://github.com/sass/sass), JavaScript is currently [Babel](https://github.com/babel/babel), (but I am in the process of converting to [TypeScript](https://github.com/Microsoft/TypeScript)), linting is done with [ESLint](https://github.com/eslint/eslint), the config is defined in [YAML](https://github.com/yaml/yaml), and there is a simple [Node.js](https://github.com/nodejs/node) server to serve up the static app.
|
At it's core, the application uses [Vue.js](https://github.com/vuejs/vue), as well as it's services. Styling is done with [SCSS](https://github.com/sass/sass), JavaScript is currently [Babel](https://github.com/babel/babel), (but I am in the process of converting to [TypeScript](https://github.com/Microsoft/TypeScript)). Linting is done with [ESLint](https://github.com/eslint/eslint) and [Prettier](https://prettier.io/), both following the [AirBnB Styleguide](https://github.com/airbnb/javascript). The config is defined in [YAML](https://github.com/yaml/yaml), and there is a simple [Node.js](https://github.com/nodejs/node) server to serve up the static app and the optional API endpoints.
|
||||||
|
|
||||||
##### Utilities
|
##### Utilities
|
||||||
- [`crypto-js`](https://github.com/brix/crypto-js) - Encryption implementations by @evanvosberg and community `MIT`
|
- [`crypto-js`](https://github.com/brix/crypto-js) - Encryption implementations by @evanvosberg and community `MIT`
|
||||||
@ -176,7 +176,7 @@ At it's core, the application uses [Vue.js](https://github.com/vuejs/vue), as we
|
|||||||
Although the app is purely frontend, there is an optional cloud backup and restore feature. This is built as a serverless function on [Cloudflare workers](https://workers.cloudflare.com/) using [KV](https://developers.cloudflare.com/workers/runtime-apis/kv) and [web crypto](https://developers.cloudflare.com/workers/runtime-apis/web-crypto)
|
Although the app is purely frontend, there is an optional cloud backup and restore feature. This is built as a serverless function on [Cloudflare workers](https://workers.cloudflare.com/) using [KV](https://developers.cloudflare.com/workers/runtime-apis/kv) and [web crypto](https://developers.cloudflare.com/workers/runtime-apis/web-crypto)
|
||||||
|
|
||||||
##### External Services
|
##### External Services
|
||||||
The 1-Click deploy demo uses [Play-with-Docker Labs](https://play-with-docker.com/). Code is hosted on [GitHub](https://github.com), Docker image is hosted on [DockerHub](https://hub.docker.com/), and the demos are hosted on [Netlify](https://www.netlify.com/).
|
The 1-Click deploy demo uses [Play-with-Docker Labs](https://play-with-docker.com/). Code is hosted on [GitHub](https://github.com), Docker images are hosted on [DockerHub](https://hub.docker.com/), and the demos are hosted on [Netlify](https://www.netlify.com/).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
8
hooks/pre_build
Normal file
8
hooks/pre_build
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Source: https://github.com/ckulka/docker-multi-arch-example/blob/master/hooks/pre_build
|
||||||
|
# Used to setup QEMU to build arm images on amd64 processors.
|
||||||
|
|
||||||
|
# Register qemu-*-static for all supported processors except the
|
||||||
|
# current one, but also remove all registered binfmt_misc before
|
||||||
|
docker run --rm --privileged multiarch/qemu-user-static:register --reset
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "Dashy",
|
"name": "Dashy",
|
||||||
"version": "1.5.4",
|
"version": "1.5.5",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "server",
|
"main": "server",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -22,7 +22,6 @@
|
|||||||
"body-parser": "^1.19.0",
|
"body-parser": "^1.19.0",
|
||||||
"connect": "^3.7.0",
|
"connect": "^3.7.0",
|
||||||
"crypto-js": "^4.0.0",
|
"crypto-js": "^4.0.0",
|
||||||
"highlight.js": "^11.0.0",
|
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"prismjs": "^1.24.1",
|
"prismjs": "^1.24.1",
|
||||||
|
@ -17,7 +17,13 @@
|
|||||||
"remember-me-never": "Never",
|
"remember-me-never": "Never",
|
||||||
"remember-me-hour": "4 Hours",
|
"remember-me-hour": "4 Hours",
|
||||||
"remember-me-day": "1 Day",
|
"remember-me-day": "1 Day",
|
||||||
"remember-me-week": "1 Week"
|
"remember-me-week": "1 Week",
|
||||||
|
"error-missing-username": "Missing Username",
|
||||||
|
"error-missing-password": "Missing Password",
|
||||||
|
"error-incorrect-username": "User not found",
|
||||||
|
"error-incorrect-password": "Incorrect Password",
|
||||||
|
"success-message": "Logging in...",
|
||||||
|
"logout-message": "Logged Out"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"main-tab": "Config",
|
"main-tab": "Config",
|
||||||
@ -59,7 +65,9 @@
|
|||||||
"item-size-small": "Small",
|
"item-size-small": "Small",
|
||||||
"item-size-medium": "Medium",
|
"item-size-medium": "Medium",
|
||||||
"item-size-large": "Large",
|
"item-size-large": "Large",
|
||||||
"config-launcher-label": "Config"
|
"config-launcher-label": "Config",
|
||||||
|
"config-launcher-tooltip": "Update Configuration",
|
||||||
|
"sign-out-tooltip": "Sign Out"
|
||||||
},
|
},
|
||||||
"updates": {
|
"updates": {
|
||||||
"app-version-note": "Dashy version",
|
"app-version-note": "Dashy version",
|
||||||
|
150
src/assets/locales/fr.json
Normal file
150
src/assets/locales/fr.json
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
{
|
||||||
|
"home": {
|
||||||
|
"no-results": "Aucun résultat",
|
||||||
|
"no-data": "Aucune donnée configurée"
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"search-label": "Recherche",
|
||||||
|
"search-placeholder": "Commencez à taper pour filtrer",
|
||||||
|
"clear-search-tooltip": "Effacer la recherche"
|
||||||
|
},
|
||||||
|
"login": {
|
||||||
|
"title": "Dashy",
|
||||||
|
"username-label": "Nom d'utilisateur",
|
||||||
|
"password-label": "Mot de passe",
|
||||||
|
"login-button": "Connexion",
|
||||||
|
"remember-me-label": "Se souvenir de moi",
|
||||||
|
"remember-me-never": "Jamais",
|
||||||
|
"remember-me-hour": "4 Heures",
|
||||||
|
"remember-me-day": "1 Jour",
|
||||||
|
"remember-me-week": "1 Semaine",
|
||||||
|
"error-missing-username": "Nom d'utilisateur manquant",
|
||||||
|
"error-missing-password": "Mot de passe manquant",
|
||||||
|
"error-incorrect-username": "Utilisateur inexistant",
|
||||||
|
"error-incorrect-password": "Mot de passe incorrect",
|
||||||
|
"success-message": "Connexion ...",
|
||||||
|
"logout-message": "Déconnexion"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"main-tab": "Configuration",
|
||||||
|
"view-config-tab": "Afficher la configuration",
|
||||||
|
"edit-config-tab": "Modifier la configuration",
|
||||||
|
"custom-css-tab": "Styles personnalisés",
|
||||||
|
"heading": "Options de Configuration",
|
||||||
|
"download-config-button": "Télécharger la configuration",
|
||||||
|
"edit-config-button": "Modifier la configuration",
|
||||||
|
"edit-css-button": "Styles personnalisés",
|
||||||
|
"cloud-sync-button": "Activer la synchro. dans le cloud",
|
||||||
|
"edit-cloud-sync-button": "Modifier la synchro. dans le cloud",
|
||||||
|
"rebuild-app-button": "Reconstruire l'application",
|
||||||
|
"change-language-button": "Changer la langue",
|
||||||
|
"reset-settings-button": "Réinitialiser les paramètres locaux",
|
||||||
|
"app-info-button": "Informations sur l'application",
|
||||||
|
"backup-note": "Il est recommandé de faire une sauvegarde de votre configuration avant d'apporter des modifications.",
|
||||||
|
"reset-config-msg-l1": "Cela supprimera tous les paramètres utilisateur du stockage local, mais n'affectera pas votre fichier 'conf.yml'.",
|
||||||
|
"reset-config-msg-l2": "Vous devez d'abord sauvegarder toutes les modifications locales si vous souhaitez les utiliser à l'avenir.",
|
||||||
|
"reset-config-msg-l3": "Êtes-vous sur de vouloir continuer ?",
|
||||||
|
"data-cleared-msg": "Données effacées avec succès",
|
||||||
|
"actions-label": "Actions",
|
||||||
|
"copy-config-label": "Copier la configuration",
|
||||||
|
"data-copied-msg": "La configuration a été copiée dans le presse-papiers",
|
||||||
|
"reset-config-label": "Réinitialiser la configuration",
|
||||||
|
"css-save-btn": "Enregistrer",
|
||||||
|
"css-note-label": "Note",
|
||||||
|
"css-note-l1": "Vous devrez actualiser la page pour que les modifications prennent effet.",
|
||||||
|
"css-note-l2": "Les modifications ne sont stockés que localement, il est donc recommandé de faire une copie de votre CSS.",
|
||||||
|
"css-note-l3": "Pour supprimer tous les styles personnalisés, supprimez le contenu et appuyez sur Enregistrer."
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"theme-label": "Thème",
|
||||||
|
"layout-label": "Disposition",
|
||||||
|
"layout-auto": "Auto",
|
||||||
|
"layout-horizontal": "Horizontal",
|
||||||
|
"layout-vertical": "Vertical",
|
||||||
|
"item-size-label": "Taille",
|
||||||
|
"item-size-small": "Petite",
|
||||||
|
"item-size-medium": "Moyenne",
|
||||||
|
"item-size-large": "Grande",
|
||||||
|
"config-launcher-label": "Config.",
|
||||||
|
"config-launcher-tooltip": "Modifier la configuration",
|
||||||
|
"sign-out-tooltip": "Déconnexion"
|
||||||
|
},
|
||||||
|
"updates": {
|
||||||
|
"app-version-note": "Version de Dashy",
|
||||||
|
"up-to-date": "À jour",
|
||||||
|
"out-of-date": "Mise à jour disponible !",
|
||||||
|
"unsupported-version-l1": "Vous utilisez une version non prise en charge de Dashy",
|
||||||
|
"unsupported-version-l2": "Pour une meilleure expérience et des correctifs de sécurité récents, veuillez mettre à jour vers"
|
||||||
|
},
|
||||||
|
"language-switcher": {
|
||||||
|
"title": "Changer la langue",
|
||||||
|
"dropdown-label": "Sélectionnez une langue",
|
||||||
|
"save-button": "Enregistrer",
|
||||||
|
"success-msg": "Langue mise à jour vers"
|
||||||
|
},
|
||||||
|
"theme-maker": {
|
||||||
|
"title": "Configurateur de Thèmes",
|
||||||
|
"export-button": "Exporter des variables personnalisées",
|
||||||
|
"reset-button": "Réinitialiser les styles pour",
|
||||||
|
"show-all-button": "Afficher toutes les variables",
|
||||||
|
"save-button": "Enregistrer",
|
||||||
|
"cancel-button": "Annuler",
|
||||||
|
"saved-toast": "{theme} mis à jour avec succès",
|
||||||
|
"copied-toast": "Données du thème {theme} copiées dans le presse-papiers",
|
||||||
|
"reset-toast": "Couleurs personnalisées pour {theme} supprimées"
|
||||||
|
},
|
||||||
|
"config-editor": {
|
||||||
|
"save-location-label": "Enregistrer localement",
|
||||||
|
"location-local-label": "Appliquer localement",
|
||||||
|
"location-disk-label": "Appliquer dans le fichier de configuration",
|
||||||
|
"save-button": "Enregistrer",
|
||||||
|
"valid-label": "La configuration est valide",
|
||||||
|
"status-success-msg": "Tâche terminée",
|
||||||
|
"status-fail-msg": "Échec de la tâche",
|
||||||
|
"success-msg-disk": "Le fichier de configuration est écrit avec succès sur le disque",
|
||||||
|
"success-msg-local": "Les modifications locales ont bien été enregistrées",
|
||||||
|
"success-note-l1": "L'application devrait se reconstruire automatiquement.",
|
||||||
|
"success-note-l2": "Cela peut prendre une minute.",
|
||||||
|
"success-note-l3": "Vous devrez actualiser la page pour que les modifications prennent effet.",
|
||||||
|
"error-msg-save-mode": "Veuillez sélectionner un mode d'enregistrement : Local ou Fichier",
|
||||||
|
"error-msg-cannot-save": "Une erreur s'est produite lors de l'enregistrement de la configuration",
|
||||||
|
"error-msg-bad-json": "Erreur dans le fichier JSON, il est peut-être mal formé",
|
||||||
|
"warning-msg-validation": "Attention"
|
||||||
|
},
|
||||||
|
"app-rebuild": {
|
||||||
|
"title": "Reconstruire l'application",
|
||||||
|
"rebuild-note-l1": "Une reconstruction est requise pour que les modifications écrites dans le fichier conf.yml prennent effet.",
|
||||||
|
"rebuild-note-l2": "Cela devrait se produire automatiquement, mais si ce n'est pas le cas, vous pouvez le déclencher manuellement ici.",
|
||||||
|
"rebuild-note-l3": "Ceci n'est pas nécessaire pour les modifications stockées localement.",
|
||||||
|
"rebuild-button": "Démarrer la reconstruction",
|
||||||
|
"rebuilding-status-1": "Reconstruction ...",
|
||||||
|
"rebuilding-status-2": "Cela peut prendre quelques minutes",
|
||||||
|
"error-permission": "Vous n'êtes pas autorisé à executer cette action",
|
||||||
|
"success-msg": "Construction terminée avec succès",
|
||||||
|
"fail-msg": "Échec de la construction",
|
||||||
|
"reload-note": "Un rechargement de la page est maintenant requis pour que les modifications prennent effet",
|
||||||
|
"reload-button": "Rafraîchir la page"
|
||||||
|
},
|
||||||
|
"cloud-sync": {
|
||||||
|
"title": "Sauvegarde Cloud & Restauration",
|
||||||
|
"intro-l1": "Ce service de sauvegarde et de restauration depuis le cloud est une fonctionnalité facultative qui vous permet de télécharger votre configuration sur Internet, puis de la restaurer sur n'importe quel autre appareil ou instance de Dashy.",
|
||||||
|
"intro-l2": "Toutes les données sont entièrement chiffrées de bout en bout avec le protocole AES, en utilisant votre mot de passe comme clé.",
|
||||||
|
"intro-l3": "Pour plus d'informations, veuillez consulter la",
|
||||||
|
"backup-title-setup": "Sauvegarder",
|
||||||
|
"backup-title-update": "Mettre à jour la sauvegarde",
|
||||||
|
"password-label-setup": "Choisissez un mot de passe",
|
||||||
|
"password-label-update": "Entrer votre mot de passe",
|
||||||
|
"backup-button-setup": "Sauvegarde",
|
||||||
|
"backup-button-update": "Mettre à jour la sauvegarde",
|
||||||
|
"backup-id-label": "Votre identifiant de sauvegarde",
|
||||||
|
"backup-id-note": "Il vous sera demandé par la suite pour restaurer à partir de votre sauvegarde. Alors gardez-le, avec votre mot de passe dans un endroit sûr.",
|
||||||
|
"restore-title": "Restauration",
|
||||||
|
"restore-id-label": "Identifiant de sauvegarde",
|
||||||
|
"restore-password-label": "Mot de passe",
|
||||||
|
"restore-button": "Restaurer",
|
||||||
|
"backup-error-unknown": "Impossible de traiter la demande",
|
||||||
|
"backup-error-password": "Mot de passe incorrect. Veuillez saisir votre mot de passe actuel.",
|
||||||
|
"backup-success-msg": "Sauvegarde effectuée avec succès",
|
||||||
|
"restore-success-msg": "Configuration restaurée avec succès"
|
||||||
|
}
|
||||||
|
}
|
@ -79,9 +79,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import hljs from 'highlight.js/lib/core';
|
|
||||||
import yaml from 'highlight.js/lib/languages/yaml';
|
|
||||||
import 'highlight.js/styles/mono-blue.css';
|
|
||||||
|
|
||||||
import JsonToYaml from '@/utils/JsonToYaml';
|
import JsonToYaml from '@/utils/JsonToYaml';
|
||||||
import { localStorageKeys, modalNames } from '@/utils/defaults';
|
import { localStorageKeys, modalNames } from '@/utils/defaults';
|
||||||
@ -179,20 +176,11 @@ export default {
|
|||||||
element.click();
|
element.click();
|
||||||
document.body.removeChild(element);
|
document.body.removeChild(element);
|
||||||
},
|
},
|
||||||
/* Highlights the YAML config in View config tab */
|
|
||||||
initiateStntaxHighlighter() {
|
|
||||||
hljs.registerLanguage('yaml', yaml);
|
|
||||||
const highlighted = hljs.highlight(this.jsonParser(this.config), { language: 'yaml' }).value;
|
|
||||||
document.getElementById('conf-yaml').innerHTML = highlighted;
|
|
||||||
},
|
|
||||||
getLanguage() {
|
getLanguage() {
|
||||||
const lang = getUsersLanguage();
|
const lang = getUsersLanguage();
|
||||||
return lang ? `${lang.flag} ${lang.name}` : '';
|
return lang ? `${lang.flag} ${lang.name}` : '';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
this.initiateStntaxHighlighter();
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
<v-jsoneditor
|
<v-jsoneditor
|
||||||
v-model="jsonData"
|
v-model="jsonData"
|
||||||
:options="options"
|
:options="options"
|
||||||
height="500px"
|
|
||||||
/>
|
/>
|
||||||
<!-- Options raido, and save button -->
|
<!-- Options raido, and save button -->
|
||||||
<div class="save-options">
|
<div class="save-options">
|
||||||
@ -293,6 +292,10 @@ div.save-options {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.jsoneditor-container.min-box {
|
||||||
|
height: 58vh;
|
||||||
|
}
|
||||||
|
|
||||||
.jsoneditor, .jsoneditor-menu {
|
.jsoneditor, .jsoneditor-menu {
|
||||||
border-color: var(--primary);
|
border-color: var(--primary);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="display-options">
|
<div class="display-options">
|
||||||
<IconLogout @click="logout()" v-tooltip="tooltip('Sign Out')"
|
<IconLogout @click="logout()" v-tooltip="tooltip($t('settings.sign-out-tooltip'))"
|
||||||
class="layout-icon" tabindex="-2" />
|
class="layout-icon" tabindex="-2" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -19,7 +19,7 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
logout() {
|
logout() {
|
||||||
registerLogout();
|
registerLogout();
|
||||||
this.$toasted.show('Logged Out');
|
this.$toasted.show(this.$t('login.logout-message'));
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
location.reload(true); // eslint-disable-line no-restricted-globals
|
location.reload(true); // eslint-disable-line no-restricted-globals
|
||||||
}, 500);
|
}, 500);
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<span>{{ $t('settings.config-launcher-label') }}</span>
|
<span>{{ $t('settings.config-launcher-label') }}</span>
|
||||||
<div class="config-buttons">
|
<div class="config-buttons">
|
||||||
<IconSpanner @click="showEditor()" tabindex="-2"
|
<IconSpanner @click="showEditor()" tabindex="-2"
|
||||||
v-tooltip="tooltip('Update configuration')" />
|
v-tooltip="tooltip($t('settings.config-launcher-tooltip'))" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Modal containing all the configuration options -->
|
<!-- Modal containing all the configuration options -->
|
||||||
@ -73,6 +73,7 @@ export default {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
color: var(--settings-text-color);
|
color: var(--settings-text-color);
|
||||||
|
min-width: 3.2rem;
|
||||||
svg {
|
svg {
|
||||||
path {
|
path {
|
||||||
fill: var(--settings-text-color);
|
fill: var(--settings-text-color);
|
||||||
|
@ -37,7 +37,6 @@ import ItemSizeSelector from '@/components/Settings/ItemSizeSelector';
|
|||||||
import AppButtons from '@/components/Settings/AppButtons';
|
import AppButtons from '@/components/Settings/AppButtons';
|
||||||
import KeyboardShortcutInfo from '@/components/Settings/KeyboardShortcutInfo';
|
import KeyboardShortcutInfo from '@/components/Settings/KeyboardShortcutInfo';
|
||||||
import AppInfoModal from '@/components/Configuration/AppInfoModal';
|
import AppInfoModal from '@/components/Configuration/AppInfoModal';
|
||||||
import { logout as registerLogout } from '@/utils/Auth';
|
|
||||||
import IconOpen from '@/assets/interface-icons/config-open-settings.svg';
|
import IconOpen from '@/assets/interface-icons/config-open-settings.svg';
|
||||||
import IconClose from '@/assets/interface-icons/config-close.svg';
|
import IconClose from '@/assets/interface-icons/config-close.svg';
|
||||||
import {
|
import {
|
||||||
@ -88,13 +87,6 @@ export default {
|
|||||||
getInitialTheme() {
|
getInitialTheme() {
|
||||||
return this.appConfig.theme || '';
|
return this.appConfig.theme || '';
|
||||||
},
|
},
|
||||||
logout() {
|
|
||||||
registerLogout();
|
|
||||||
this.$toasted.show('Logged Out');
|
|
||||||
setTimeout(() => {
|
|
||||||
location.reload(true); // eslint-disable-line no-restricted-globals
|
|
||||||
}, 100);
|
|
||||||
},
|
|
||||||
isUserLoggedIn() {
|
isUserLoggedIn() {
|
||||||
return !!localStorage[localStorageKeys.USERNAME];
|
return !!localStorage[localStorageKeys.USERNAME];
|
||||||
},
|
},
|
||||||
@ -199,25 +191,6 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
svg.logout-icon {
|
|
||||||
path {
|
|
||||||
fill: var(--settings-text-color);
|
|
||||||
}
|
|
||||||
width: 1rem;
|
|
||||||
height: 1rem;
|
|
||||||
margin: 0.35rem 0.2rem;
|
|
||||||
padding: 0.2rem;
|
|
||||||
text-align: center;
|
|
||||||
background: var(--background);
|
|
||||||
border: 1px solid var(--settings-text-color);;
|
|
||||||
border-radius: var(--curve-factor);
|
|
||||||
cursor: pointer;
|
|
||||||
&:hover, &.selected {
|
|
||||||
background: var(--settings-text-color);
|
|
||||||
path { fill: var(--background); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@include tablet {
|
@include tablet {
|
||||||
section {
|
section {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -126,6 +126,7 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|
||||||
@import 'vue-select/src/scss/vue-select.scss';
|
@import 'vue-select/src/scss/vue-select.scss';
|
||||||
|
@import '@/styles/style-helpers.scss';
|
||||||
|
|
||||||
.theme-dropdown {
|
.theme-dropdown {
|
||||||
div.vs__dropdown-toggle {
|
div.vs__dropdown-toggle {
|
||||||
@ -146,10 +147,13 @@ export default {
|
|||||||
}
|
}
|
||||||
ul.vs__dropdown-menu {
|
ul.vs__dropdown-menu {
|
||||||
width: auto;
|
width: auto;
|
||||||
background: var(--background);
|
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
max-width: 13rem;
|
max-width: 13rem;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
@extend .scroll-bar;
|
||||||
|
background: var(--background);
|
||||||
|
border-radius: var(--curve-factor);
|
||||||
|
border-top: 1px solid var(--settings-text-color);
|
||||||
}
|
}
|
||||||
li.vs__dropdown-option--highlight {
|
li.vs__dropdown-option--highlight {
|
||||||
background: var(--settings-text-color);
|
background: var(--settings-text-color);
|
||||||
|
@ -498,7 +498,7 @@ html[data-theme='material'] {
|
|||||||
--nav-link-border-color: #0c4eba;
|
--nav-link-border-color: #0c4eba;
|
||||||
--settings-text-color: #363636;
|
--settings-text-color: #363636;
|
||||||
--config-code-color: #363636;
|
--config-code-color: #363636;
|
||||||
--config-settings-background: #fff;
|
--config-settings-background: #f5f5f5;
|
||||||
--config-settings-color: #473f3f;
|
--config-settings-color: #473f3f;
|
||||||
--heading-text-color: #fff;
|
--heading-text-color: #fff;
|
||||||
--curve-factor: 4px;
|
--curve-factor: 4px;
|
||||||
@ -508,6 +508,11 @@ html[data-theme='material'] {
|
|||||||
--footer-text-color: #f5f5f5cc;
|
--footer-text-color: #f5f5f5cc;
|
||||||
// --login-form-background-secondary: #f5f5f5cc;
|
// --login-form-background-secondary: #f5f5f5cc;
|
||||||
--context-menu-secondary-color: #f5f5f5;
|
--context-menu-secondary-color: #f5f5f5;
|
||||||
|
--transparent-white-50: #00000080;
|
||||||
|
|
||||||
|
div.jsoneditor div.jsoneditor-menu {
|
||||||
|
background: #5c90eb !important;
|
||||||
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
background: #4285f4;
|
background: #4285f4;
|
||||||
|
@ -43,24 +43,24 @@ export const isLoggedIn = (users) => {
|
|||||||
* @param {String[]} users An array of valid user objects
|
* @param {String[]} users An array of valid user objects
|
||||||
* @returns {Object} An object containing a boolean result and a message
|
* @returns {Object} An object containing a boolean result and a message
|
||||||
*/
|
*/
|
||||||
export const checkCredentials = (username, pass, users) => {
|
export const checkCredentials = (username, pass, users, messages) => {
|
||||||
let response;
|
let response; // Will store an object containing boolean and message
|
||||||
if (!username) {
|
if (!username) {
|
||||||
response = { correct: false, msg: 'Missing Username' };
|
response = { correct: false, msg: messages.missingUsername };
|
||||||
} else if (!pass) {
|
} else if (!pass) {
|
||||||
response = { correct: false, msg: 'Missing Password' };
|
response = { correct: false, msg: messages.missingPassword };
|
||||||
} else {
|
} else {
|
||||||
users.forEach((user) => {
|
users.forEach((user) => {
|
||||||
if (user.user.toLowerCase() === username.toLowerCase()) {
|
if (user.user.toLowerCase() === username.toLowerCase()) { // User found
|
||||||
if (user.hash.toLowerCase() === sha256(pass).toString().toLowerCase()) {
|
if (user.hash.toLowerCase() === sha256(pass).toString().toLowerCase()) {
|
||||||
response = { correct: true, msg: 'Logging in...' };
|
response = { correct: true, msg: messages.successMsg }; // Password is correct
|
||||||
} else {
|
} else { // User found, but password is not a match
|
||||||
response = { correct: false, msg: 'Incorrect Password' };
|
response = { correct: false, msg: messages.incorrectPassword };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return response || { correct: false, msg: 'User not found' };
|
return response || { correct: false, msg: messages.incorrectUsername };
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import en from '@/assets/locales/en.json';
|
import en from '@/assets/locales/en.json';
|
||||||
import de from '@/assets/locales/de.json';
|
import de from '@/assets/locales/de.json';
|
||||||
import nl from '@/assets/locales/nl.json';
|
import nl from '@/assets/locales/nl.json';
|
||||||
|
import fr from '@/assets/locales/fr.json';
|
||||||
|
|
||||||
// Language data - Add your country name, locale code and imported file here
|
// Language data - Add your country name, locale code and imported file here
|
||||||
export const languages = [
|
export const languages = [
|
||||||
@ -23,6 +24,12 @@ export const languages = [
|
|||||||
locale: nl,
|
locale: nl,
|
||||||
flag: '🇳🇱',
|
flag: '🇳🇱',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'French',
|
||||||
|
code: 'fr',
|
||||||
|
locale: fr,
|
||||||
|
flag: '🇲🇫',
|
||||||
|
},
|
||||||
// Including:
|
// Including:
|
||||||
// name - Human readable name for your language (e.g German)
|
// name - Human readable name for your language (e.g German)
|
||||||
// code - ISO language code (e.g. de)
|
// code - ISO language code (e.g. de)
|
||||||
|
@ -218,7 +218,7 @@ export default {
|
|||||||
padding-bottom: 1px;
|
padding-bottom: 1px;
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
// min-height: calc(100vh - 126px);
|
// min-height: calc(100vh - 126px);
|
||||||
min-height: calc(100vh - var(--footer-height));
|
min-height: calc(99.9vh - var(--footer-height));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Outside container wrapping the item groups*/
|
/* Outside container wrapping the item groups*/
|
||||||
|
@ -40,6 +40,10 @@ import { checkCredentials, login } from '@/utils/Auth';
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'login',
|
name: 'login',
|
||||||
|
components: {
|
||||||
|
Button,
|
||||||
|
Input,
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
appConfig: Object,
|
appConfig: Object,
|
||||||
},
|
},
|
||||||
@ -50,23 +54,41 @@ export default {
|
|||||||
message: '',
|
message: '',
|
||||||
status: 'waiting', // wating, error, success
|
status: 'waiting', // wating, error, success
|
||||||
timeout: { label: this.$t('login.remember-me-never'), time: 0 },
|
timeout: { label: this.$t('login.remember-me-never'), time: 0 },
|
||||||
dropDownMenu: [ // Data for timeout dropdown menu, translated label + value in ms
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
/* Data for timeout dropdown menu, translated label + value in ms */
|
||||||
|
dropDownMenu() {
|
||||||
|
return [
|
||||||
{ label: this.$t('login.remember-me-never'), time: 0 },
|
{ label: this.$t('login.remember-me-never'), time: 0 },
|
||||||
{ label: this.$t('login.remember-me-hour'), time: 14400 * 1000 },
|
{ label: this.$t('login.remember-me-hour'), time: 14400 * 1000 },
|
||||||
{ label: this.$t('login.remember-me-day'), time: 86400 * 1000 },
|
{ label: this.$t('login.remember-me-day'), time: 86400 * 1000 },
|
||||||
{ label: this.$t('login.remember-me-week'), time: 604800 * 1000 },
|
{ label: this.$t('login.remember-me-week'), time: 604800 * 1000 },
|
||||||
],
|
];
|
||||||
};
|
},
|
||||||
},
|
/* Translations for login response messages */
|
||||||
components: {
|
responseMessages() {
|
||||||
Button,
|
return {
|
||||||
Input,
|
missingUsername: this.$t('login.error-missing-username'),
|
||||||
|
missingPassword: this.$t('login.error-missing-password'),
|
||||||
|
incorrectUsername: this.$t('login.error-incorrect-username'),
|
||||||
|
incorrectPassword: this.$t('login.error-incorrect-password'),
|
||||||
|
successMsg: this.$t('login.success-message'),
|
||||||
|
};
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/* Checks form is filled in, then initiates the login, and redirects to /home */
|
/* Checks form is filled in, then initiates the login, and redirects to /home */
|
||||||
submitLogin() {
|
submitLogin() {
|
||||||
|
// Use selected timeout, if available,else revedrt to zero
|
||||||
const timeout = this.timeout ? this.timeout.time : 0;
|
const timeout = this.timeout ? this.timeout.time : 0;
|
||||||
const response = checkCredentials(this.username, this.password, this.appConfig.auth || []);
|
// Check users credentials
|
||||||
|
const response = checkCredentials(
|
||||||
|
this.username,
|
||||||
|
this.password,
|
||||||
|
this.appConfig.auth || [], // All users
|
||||||
|
this.responseMessages, // Translated response messages
|
||||||
|
);
|
||||||
this.message = response.msg; // Show error or success message to the user
|
this.message = response.msg; // Show error or success message to the user
|
||||||
this.status = response.correct ? 'success' : 'error';
|
this.status = response.correct ? 'success' : 'error';
|
||||||
if (response.correct) { // Yay, credentials were correct :)
|
if (response.correct) { // Yay, credentials were correct :)
|
||||||
@ -76,7 +98,7 @@ export default {
|
|||||||
}, 250);
|
}, 250);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/* Since we don't have the Theme setter at this point, we must manually set users theme */
|
/* Since Theme setter isn't loaded at this point, we must manually get and apply users theme */
|
||||||
setTheme() {
|
setTheme() {
|
||||||
const theme = localStorage[localStorageKeys.THEME] || Defaults.theme;
|
const theme = localStorage[localStorageKeys.THEME] || Defaults.theme;
|
||||||
document.getElementsByTagName('html')[0].setAttribute('data-theme', theme);
|
document.getElementsByTagName('html')[0].setAttribute('data-theme', theme);
|
||||||
|
@ -5045,11 +5045,6 @@ highlight.js@^10.7.1:
|
|||||||
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531"
|
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531"
|
||||||
integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==
|
integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==
|
||||||
|
|
||||||
highlight.js@^11.0.0:
|
|
||||||
version "11.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.1.0.tgz#0198f7326e64ddfbea5f76b00e84ab542cf24ae8"
|
|
||||||
integrity sha512-X9VVhYKHQPPuwffO8jk4bP/FVj+ibNCy3HxZZNDXFtJrq4O5FdcdCDRIkDis5MiMnjh7UwEdHgRZJcHFYdzDdA==
|
|
||||||
|
|
||||||
hmac-drbg@^1.0.1:
|
hmac-drbg@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
|
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
|
||||||
|
Loading…
Reference in New Issue
Block a user