mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-12-18 02:47:24 +00:00
Merge pull request #2915 from kiznick/badge-generator
Feat: Badge Generator
This commit is contained in:
commit
039fdb0730
4 changed files with 432 additions and 15 deletions
299
src/components/BadgeGeneratorDialog.vue
Normal file
299
src/components/BadgeGeneratorDialog.vue
Normal file
|
@ -0,0 +1,299 @@
|
||||||
|
<template>
|
||||||
|
<div ref="BadgeGeneratorModal" class="modal fade" tabindex="-1" data-bs-backdrop="static">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">
|
||||||
|
{{ $t("Badge Generator", [monitor.name]) }}
|
||||||
|
</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" />
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="type" class="form-label">{{ $t("Badge Type") }}</label>
|
||||||
|
<select id="type" v-model="badge.type" class="form-select">
|
||||||
|
<option value="status">status</option>
|
||||||
|
<option value="uptime">uptime</option>
|
||||||
|
<option value="ping">ping</option>
|
||||||
|
<option value="avg-response">avg-response</option>
|
||||||
|
<option value="cert-exp">cert-exp</option>
|
||||||
|
<option value="response">response</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if=" (parameters[badge.type || 'null'] || [] ).includes('duration') " class="mb-3">
|
||||||
|
<label for="duration" class="form-label">{{ $t("Badge Duration") }}</label>
|
||||||
|
<input id="duration" v-model="badge.duration" type="number" min="0" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if=" (parameters[badge.type || 'null'] || [] ).includes('label') " class="mb-3">
|
||||||
|
<label for="label" class="form-label">{{ $t("Badge Label") }}</label>
|
||||||
|
<input id="label" v-model="badge.label" type="text" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if=" (parameters[badge.type || 'null'] || [] ).includes('prefix') " class="mb-3">
|
||||||
|
<label for="prefix" class="form-label">{{ $t("Badge Prefix") }}</label>
|
||||||
|
<input id="prefix" v-model="badge.prefix" type="text" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if=" (parameters[badge.type || 'null'] || [] ).includes('suffix') " class="mb-3">
|
||||||
|
<label for="suffix" class="form-label">{{ $t("Badge Suffix") }}</label>
|
||||||
|
<input id="suffix" v-model="badge.suffix" type="text" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if=" (parameters[badge.type || 'null'] || [] ).includes('labelColor') " class="mb-3">
|
||||||
|
<label for="labelColor" class="form-label">{{ $t("Badge Label Color") }}</label>
|
||||||
|
<input id="labelColor" v-model="badge.labelColor" type="text" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if=" (parameters[badge.type || 'null'] || [] ).includes('color') " class="mb-3">
|
||||||
|
<label for="color" class="form-label">{{ $t("Badge Color") }}</label>
|
||||||
|
<input id="color" v-model="badge.color" type="text" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if=" (parameters[badge.type || 'null'] || [] ).includes('labelPrefix') " class="mb-3">
|
||||||
|
<label for="labelPrefix" class="form-label">{{ $t("Badge Label Prefix") }}</label>
|
||||||
|
<input id="labelPrefix" v-model="badge.labelPrefix" type="text" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if=" (parameters[badge.type || 'null'] || [] ).includes('labelSuffix') " class="mb-3">
|
||||||
|
<label for="labelSuffix" class="form-label">{{ $t("Badge Label Suffix") }}</label>
|
||||||
|
<input id="labelSuffix" v-model="badge.labelSuffix" type="text" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if=" (parameters[badge.type || 'null'] || [] ).includes('upColor') " class="mb-3">
|
||||||
|
<label for="upColor" class="form-label">{{ $t("Badge Up Color") }}</label>
|
||||||
|
<input id="upColor" v-model="badge.upColor" type="text" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if=" (parameters[badge.type || 'null'] || [] ).includes('downColor') " class="mb-3">
|
||||||
|
<label for="downColor" class="form-label">{{ $t("Badge Down Color") }}</label>
|
||||||
|
<input id="downColor" v-model="badge.downColor" type="text" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if=" (parameters[badge.type || 'null'] || [] ).includes('pendingColor') " class="mb-3">
|
||||||
|
<label for="pendingColor" class="form-label">{{ $t("Badge Pending Color") }}</label>
|
||||||
|
<input id="pendingColor" v-model="badge.pendingColor" type="text" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if=" (parameters[badge.type || 'null'] || [] ).includes('maintenanceColor') " class="mb-3">
|
||||||
|
<label for="maintenanceColor" class="form-label">{{ $t("Badge Maintenance Color") }}</label>
|
||||||
|
<input id="maintenanceColor" v-model="badge.maintenanceColor" type="text" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if=" (parameters[badge.type || 'null'] || [] ).includes('warnColor') " class="mb-3">
|
||||||
|
<label for="warnColor" class="form-label">{{ $t("Badge Warn Color") }}</label>
|
||||||
|
<input id="warnColor" v-model="badge.warnColor" type="number" min="0" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if=" (parameters[badge.type || 'null'] || [] ).includes('warnDays') " class="mb-3">
|
||||||
|
<label for="warnDays" class="form-label">{{ $t("Badge Warn Days") }}</label>
|
||||||
|
<input id="warnDays" v-model="badge.warnDays" type="number" min="0" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if=" (parameters[badge.type || 'null'] || [] ).includes('downDays') " class="mb-3">
|
||||||
|
<label for="downDays" class="form-label">{{ $t("Badge Down Days") }}</label>
|
||||||
|
<input id="downDays" v-model="badge.downDays" type="number" min="0" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="style" class="form-label">{{ $t("Badge Style") }}</label>
|
||||||
|
<select id="style" v-model="badge.style" class="form-select">
|
||||||
|
<option value="plastic">plastic</option>
|
||||||
|
<option value="flat">flat</option>
|
||||||
|
<option value="flat-square">flat-square</option>
|
||||||
|
<option value="for-the-badge">for-the-badge</option>
|
||||||
|
<option value="social">social</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="value" class="form-label">{{ $t("Badge value (For Testing only.)") }}</label>
|
||||||
|
<input id="value" v-model="badge.value" type="text" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="my-3">
|
||||||
|
<label for="push-url" class="form-label">{{ $t("Badge URL") }}</label>
|
||||||
|
<CopyableInput id="push-url" v-model="badgeURL" type="url" disabled="disabled" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="submit" class="btn btn-danger" data-bs-dismiss="modal">
|
||||||
|
{{ $t("Close") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Modal } from "bootstrap";
|
||||||
|
import CopyableInput from "./CopyableInput.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
CopyableInput
|
||||||
|
},
|
||||||
|
props: {},
|
||||||
|
emits: [],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
model: null,
|
||||||
|
processing: false,
|
||||||
|
monitor: {
|
||||||
|
id: null,
|
||||||
|
name: null,
|
||||||
|
},
|
||||||
|
badge: {
|
||||||
|
type: "status",
|
||||||
|
duration: null,
|
||||||
|
label: null,
|
||||||
|
prefix: null,
|
||||||
|
suffix: null,
|
||||||
|
labelColor: null,
|
||||||
|
color: null,
|
||||||
|
labelPrefix: null,
|
||||||
|
labelSuffix: null,
|
||||||
|
upColor: null,
|
||||||
|
downColor: null,
|
||||||
|
pendingColor: null,
|
||||||
|
maintenanceColor: null,
|
||||||
|
warnColor: null,
|
||||||
|
warnDays: null,
|
||||||
|
downDays: null,
|
||||||
|
style: "flat",
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
status: [
|
||||||
|
"upLabel",
|
||||||
|
"downLabel",
|
||||||
|
"pendingLabel",
|
||||||
|
"maintenanceLabel",
|
||||||
|
"upColor",
|
||||||
|
"downColor",
|
||||||
|
"pendingColor",
|
||||||
|
"maintenanceColor",
|
||||||
|
],
|
||||||
|
uptime: [
|
||||||
|
"duration",
|
||||||
|
"labelPrefix",
|
||||||
|
"labelSuffix",
|
||||||
|
"prefix",
|
||||||
|
"suffix",
|
||||||
|
"color",
|
||||||
|
"labelColor",
|
||||||
|
],
|
||||||
|
ping: [
|
||||||
|
"duration",
|
||||||
|
"labelPrefix",
|
||||||
|
"labelSuffix",
|
||||||
|
"prefix",
|
||||||
|
"suffix",
|
||||||
|
"color",
|
||||||
|
"labelColor",
|
||||||
|
],
|
||||||
|
"avg-response": [
|
||||||
|
"duration",
|
||||||
|
"labelPrefix",
|
||||||
|
"labelSuffix",
|
||||||
|
"prefix",
|
||||||
|
"suffix",
|
||||||
|
"color",
|
||||||
|
"labelColor",
|
||||||
|
],
|
||||||
|
"cert-exp": [
|
||||||
|
"labelPrefix",
|
||||||
|
"labelSuffix",
|
||||||
|
"prefix",
|
||||||
|
"suffix",
|
||||||
|
"upColor",
|
||||||
|
"warnColor",
|
||||||
|
"downColor",
|
||||||
|
"warnDays",
|
||||||
|
"downDays",
|
||||||
|
"labelColor",
|
||||||
|
],
|
||||||
|
response: [
|
||||||
|
"labelPrefix",
|
||||||
|
"labelSuffix",
|
||||||
|
"prefix",
|
||||||
|
"suffix",
|
||||||
|
"color",
|
||||||
|
"labelColor",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
badgeURL() {
|
||||||
|
if (!this.monitor.id || !this.badge.type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let badgeURL = this.$root.baseURL + "/api/badge/" + this.monitor.id + "/" + this.badge.type;
|
||||||
|
|
||||||
|
let parameterList = {};
|
||||||
|
|
||||||
|
for (let parameter of this.parameters[this.badge.type] || []) {
|
||||||
|
if (parameter === "duration" && this.badge.duration) {
|
||||||
|
badgeURL += "/" + this.badge.duration;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.badge[parameter]) {
|
||||||
|
parameterList[parameter] = this.badge[parameter];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let parameter of [ "label", "style", "value" ]) {
|
||||||
|
if (parameter === "style" && this.badge.style === "flat") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.badge[parameter]) {
|
||||||
|
parameterList[parameter] = this.badge[parameter];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(parameterList).length > 0) {
|
||||||
|
return badgeURL + "?" + new URLSearchParams(parameterList);
|
||||||
|
}
|
||||||
|
|
||||||
|
return badgeURL;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.BadgeGeneratorModal = new Modal(this.$refs.BadgeGeneratorModal);
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* Setting monitor
|
||||||
|
* @param {number} monitorId ID of monitor
|
||||||
|
* @param {string} monitorName Name of monitor
|
||||||
|
*/
|
||||||
|
show(monitorId, monitorName) {
|
||||||
|
this.monitor = {
|
||||||
|
id: monitorId,
|
||||||
|
name: monitorName,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.BadgeGeneratorModal.show();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../assets/vars.scss";
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
.modal-dialog .form-text, .modal-dialog p {
|
||||||
|
color: $dark-font-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
123
src/components/MonitorSettingDialog.vue
Normal file
123
src/components/MonitorSettingDialog.vue
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
<template>
|
||||||
|
<div ref="MonitorSettingDialog" class="modal fade" tabindex="-1">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">
|
||||||
|
{{ $t("Monitor Setting", [monitor.name]) }}
|
||||||
|
</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" />
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="my-3 form-check">
|
||||||
|
<input id="show-clickable-link" v-model="monitor.isClickAble" class="form-check-input" type="checkbox" @click="toggleLink(monitor.group_index, monitor.monitor_index)" />
|
||||||
|
<label class="form-check-label" for="show-clickable-link">
|
||||||
|
{{ $t("Show Clickable Link") }}
|
||||||
|
</label>
|
||||||
|
<div class="form-text">
|
||||||
|
{{ $t("Show Clickable Link Description") }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="btn btn-primary btn-add-group me-2"
|
||||||
|
@click="$refs.badgeGeneratorDialog.show(monitor.id, monitor.name)"
|
||||||
|
>
|
||||||
|
<font-awesome-icon icon="certificate" />
|
||||||
|
{{ $t("Open Badge Generator") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="submit" class="btn btn-danger" data-bs-dismiss="modal">
|
||||||
|
{{ $t("Close") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<BadgeGeneratorDialog ref="badgeGeneratorDialog" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Modal } from "bootstrap";
|
||||||
|
import BadgeGeneratorDialog from "./BadgeGeneratorDialog.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
BadgeGeneratorDialog
|
||||||
|
},
|
||||||
|
props: {},
|
||||||
|
emits: [],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
monitor: {
|
||||||
|
id: null,
|
||||||
|
name: null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.MonitorSettingDialog = new Modal(this.$refs.MonitorSettingDialog);
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* Setting monitor
|
||||||
|
* @param {Object} group Data of monitor
|
||||||
|
* @param {Object} monitor Data of monitor
|
||||||
|
*/
|
||||||
|
show(group, monitor) {
|
||||||
|
this.monitor = {
|
||||||
|
id: monitor.element.id,
|
||||||
|
name: monitor.element.name,
|
||||||
|
monitor_index: monitor.index,
|
||||||
|
group_index: group.index,
|
||||||
|
isClickAble: this.showLink(monitor),
|
||||||
|
};
|
||||||
|
|
||||||
|
this.MonitorSettingDialog.show();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle the value of sendUrl
|
||||||
|
* @param {number} groupIndex Index of group monitor is member of
|
||||||
|
* @param {number} index Index of monitor within group
|
||||||
|
*/
|
||||||
|
toggleLink(groupIndex, index) {
|
||||||
|
this.$root.publicGroupList[groupIndex].monitorList[index].sendUrl = !this.$root.publicGroupList[groupIndex].monitorList[index].sendUrl;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should a link to the monitor be shown?
|
||||||
|
* Attempts to guess if a link should be shown based upon if
|
||||||
|
* sendUrl is set and if the URL is default or not.
|
||||||
|
* @param {Object} monitor Monitor to check
|
||||||
|
* @param {boolean} [ignoreSendUrl=false] Should the presence of the sendUrl
|
||||||
|
* property be ignored. This will only work in edit mode.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
showLink(monitor, ignoreSendUrl = false) {
|
||||||
|
// We must check if there are any elements in monitorList to
|
||||||
|
// prevent undefined errors if it hasn't been loaded yet
|
||||||
|
if (this.$parent.editMode && ignoreSendUrl && Object.keys(this.$root.monitorList).length) {
|
||||||
|
return this.$root.monitorList[monitor.element.id].type === "http" || this.$root.monitorList[monitor.element.id].type === "keyword";
|
||||||
|
}
|
||||||
|
return monitor.element.sendUrl && monitor.element.url && monitor.element.url !== "https://" && !this.editMode;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../assets/vars.scss";
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
.modal-dialog .form-text, .modal-dialog p {
|
||||||
|
color: $dark-font-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -49,16 +49,15 @@
|
||||||
{{ monitor.element.name }}
|
{{ monitor.element.name }}
|
||||||
</a>
|
</a>
|
||||||
<p v-else class="item-name"> {{ monitor.element.name }} </p>
|
<p v-else class="item-name"> {{ monitor.element.name }} </p>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
v-if="showLink(monitor, true)"
|
title="Setting"
|
||||||
title="Toggle Clickable Link"
|
|
||||||
>
|
>
|
||||||
<font-awesome-icon
|
<font-awesome-icon
|
||||||
v-if="editMode"
|
v-if="editMode"
|
||||||
:class="{'link-active': monitor.element.sendUrl, 'btn-link': true}"
|
:class="{'link-active': true, 'btn-link': true}"
|
||||||
icon="link" class="action me-3"
|
icon="cog" class="action me-3"
|
||||||
|
@click="$refs.monitorSettingDialog.show(group, monitor)"
|
||||||
@click="toggleLink(group.index, monitor.index)"
|
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -77,9 +76,11 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</Draggable>
|
</Draggable>
|
||||||
|
<MonitorSettingDialog ref="monitorSettingDialog" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import MonitorSettingDialog from "./MonitorSettingDialog.vue";
|
||||||
import Draggable from "vuedraggable";
|
import Draggable from "vuedraggable";
|
||||||
import HeartbeatBar from "./HeartbeatBar.vue";
|
import HeartbeatBar from "./HeartbeatBar.vue";
|
||||||
import Uptime from "./Uptime.vue";
|
import Uptime from "./Uptime.vue";
|
||||||
|
@ -87,6 +88,7 @@ import Tag from "./Tag.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
MonitorSettingDialog,
|
||||||
Draggable,
|
Draggable,
|
||||||
HeartbeatBar,
|
HeartbeatBar,
|
||||||
Uptime,
|
Uptime,
|
||||||
|
@ -135,15 +137,6 @@ export default {
|
||||||
this.$root.publicGroupList[groupIndex].monitorList.splice(index, 1);
|
this.$root.publicGroupList[groupIndex].monitorList.splice(index, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggle the value of sendUrl
|
|
||||||
* @param {number} groupIndex Index of group monitor is member of
|
|
||||||
* @param {number} index Index of monitor within group
|
|
||||||
*/
|
|
||||||
toggleLink(groupIndex, index) {
|
|
||||||
this.$root.publicGroupList[groupIndex].monitorList[index].sendUrl = !this.$root.publicGroupList[groupIndex].monitorList[index].sendUrl;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should a link to the monitor be shown?
|
* Should a link to the monitor be shown?
|
||||||
* Attempts to guess if a link should be shown based upon if
|
* Attempts to guess if a link should be shown based upon if
|
||||||
|
|
|
@ -49,6 +49,7 @@ import {
|
||||||
faFilter,
|
faFilter,
|
||||||
faInfoCircle,
|
faInfoCircle,
|
||||||
faClone,
|
faClone,
|
||||||
|
faCertificate,
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
|
@ -95,6 +96,7 @@ library.add(
|
||||||
faFilter,
|
faFilter,
|
||||||
faInfoCircle,
|
faInfoCircle,
|
||||||
faClone,
|
faClone,
|
||||||
|
faCertificate,
|
||||||
);
|
);
|
||||||
|
|
||||||
export { FontAwesomeIcon };
|
export { FontAwesomeIcon };
|
||||||
|
|
Loading…
Reference in a new issue