Improve admin page
This commit is contained in:
		
							parent
							
								
									8ae94c034d
								
							
						
					
					
						commit
						6f1e2f6636
					
				
					 3 changed files with 148 additions and 118 deletions
				
			
		| 
						 | 
					@ -1080,10 +1080,10 @@ admin/views/index.vue:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
admin/views/dashboard.vue:
 | 
					admin/views/dashboard.vue:
 | 
				
			||||||
  dashboard: "ダッシュボード"
 | 
					  dashboard: "ダッシュボード"
 | 
				
			||||||
  all-users: "全てのユーザー"
 | 
					  accounts: "アカウント"
 | 
				
			||||||
  original-users: "このインスタンスのユーザー"
 | 
					  notes: "投稿"
 | 
				
			||||||
  all-notes: "全ての投稿"
 | 
					  this-instance: "このインスタンス"
 | 
				
			||||||
  original-notes: "このインスタンスの投稿"
 | 
					  federated: "連合"
 | 
				
			||||||
  invite: "招待"
 | 
					  invite: "招待"
 | 
				
			||||||
  banner-url: "Banner URL"
 | 
					  banner-url: "Banner URL"
 | 
				
			||||||
  disableRegistration: "Disable new user registration"
 | 
					  disableRegistration: "Disable new user registration"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,79 +1,38 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="zyknedwtlthezamcjlolyusmipqmjgxz">
 | 
					<div class="zyknedwtlthezamcjlolyusmipqmjgxz">
 | 
				
			||||||
	<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
 | 
						<div ref="cpu"></div>
 | 
				
			||||||
		<defs>
 | 
						<div ref="mem"></div>
 | 
				
			||||||
			<linearGradient :id="cpuGradientId" x1="0" x2="0" y1="1" y2="0">
 | 
					 | 
				
			||||||
				<stop offset="0%" stop-color="hsl(180, 80%, 70%)"></stop>
 | 
					 | 
				
			||||||
				<stop offset="100%" stop-color="hsl(0, 80%, 70%)"></stop>
 | 
					 | 
				
			||||||
			</linearGradient>
 | 
					 | 
				
			||||||
			<mask :id="cpuMaskId" x="0" y="0" :width="viewBoxX" :height="viewBoxY">
 | 
					 | 
				
			||||||
				<polygon
 | 
					 | 
				
			||||||
					:points="cpuPolygonPoints"
 | 
					 | 
				
			||||||
					fill="#fff"
 | 
					 | 
				
			||||||
					fill-opacity="0.5"/>
 | 
					 | 
				
			||||||
				<polyline
 | 
					 | 
				
			||||||
					:points="cpuPolylinePoints"
 | 
					 | 
				
			||||||
					fill="none"
 | 
					 | 
				
			||||||
					stroke="#fff"
 | 
					 | 
				
			||||||
					stroke-width="1"/>
 | 
					 | 
				
			||||||
			</mask>
 | 
					 | 
				
			||||||
		</defs>
 | 
					 | 
				
			||||||
		<rect
 | 
					 | 
				
			||||||
			x="0" y="0"
 | 
					 | 
				
			||||||
			:width="viewBoxX" :height="viewBoxY"
 | 
					 | 
				
			||||||
			:style="`stroke: none; fill: url(#${ cpuGradientId }); mask: url(#${ cpuMaskId })`"/>
 | 
					 | 
				
			||||||
		<text x="1" y="12">CPU <tspan>{{ cpuP }}%</tspan></text>
 | 
					 | 
				
			||||||
	</svg>
 | 
					 | 
				
			||||||
	<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
 | 
					 | 
				
			||||||
		<defs>
 | 
					 | 
				
			||||||
			<linearGradient :id="memGradientId" x1="0" x2="0" y1="1" y2="0">
 | 
					 | 
				
			||||||
				<stop offset="0%" stop-color="hsl(180, 80%, 70%)"></stop>
 | 
					 | 
				
			||||||
				<stop offset="100%" stop-color="hsl(0, 80%, 70%)"></stop>
 | 
					 | 
				
			||||||
			</linearGradient>
 | 
					 | 
				
			||||||
			<mask :id="memMaskId" x="0" y="0" :width="viewBoxX" :height="viewBoxY">
 | 
					 | 
				
			||||||
				<polygon
 | 
					 | 
				
			||||||
					:points="memPolygonPoints"
 | 
					 | 
				
			||||||
					fill="#fff"
 | 
					 | 
				
			||||||
					fill-opacity="0.5"/>
 | 
					 | 
				
			||||||
				<polyline
 | 
					 | 
				
			||||||
					:points="memPolylinePoints"
 | 
					 | 
				
			||||||
					fill="none"
 | 
					 | 
				
			||||||
					stroke="#fff"
 | 
					 | 
				
			||||||
					stroke-width="1"/>
 | 
					 | 
				
			||||||
			</mask>
 | 
					 | 
				
			||||||
		</defs>
 | 
					 | 
				
			||||||
		<rect
 | 
					 | 
				
			||||||
			x="0" y="0"
 | 
					 | 
				
			||||||
			:width="viewBoxX" :height="viewBoxY"
 | 
					 | 
				
			||||||
			:style="`stroke: none; fill: url(#${ memGradientId }); mask: url(#${ memMaskId })`"/>
 | 
					 | 
				
			||||||
		<text x="1" y="12">MEM <tspan>{{ memP }}%</tspan></text>
 | 
					 | 
				
			||||||
	</svg>
 | 
					 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
import Vue from 'vue';
 | 
					import Vue from 'vue';
 | 
				
			||||||
import * as uuid from 'uuid';
 | 
					import * as ApexCharts from 'apexcharts';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default Vue.extend({
 | 
					export default Vue.extend({
 | 
				
			||||||
	props: ['connection'],
 | 
						props: ['connection'],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data() {
 | 
						data() {
 | 
				
			||||||
		return {
 | 
							return {
 | 
				
			||||||
			viewBoxX: 200,
 | 
					 | 
				
			||||||
			viewBoxY: 70,
 | 
					 | 
				
			||||||
			stats: [],
 | 
								stats: [],
 | 
				
			||||||
			cpuGradientId: uuid(),
 | 
								cpuChart: null,
 | 
				
			||||||
			cpuMaskId: uuid(),
 | 
								memChart: null,
 | 
				
			||||||
			memGradientId: uuid(),
 | 
					 | 
				
			||||||
			memMaskId: uuid(),
 | 
					 | 
				
			||||||
			cpuPolylinePoints: '',
 | 
					 | 
				
			||||||
			memPolylinePoints: '',
 | 
					 | 
				
			||||||
			cpuPolygonPoints: '',
 | 
					 | 
				
			||||||
			memPolygonPoints: '',
 | 
					 | 
				
			||||||
			cpuP: '',
 | 
								cpuP: '',
 | 
				
			||||||
			memP: ''
 | 
								memP: ''
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						watch: {
 | 
				
			||||||
 | 
							stats(stats) {
 | 
				
			||||||
 | 
								this.cpuChart.updateSeries([{
 | 
				
			||||||
 | 
									data: stats.map((x, i) => ({ x: i, y: x.cpu_usage }))
 | 
				
			||||||
 | 
								}]);
 | 
				
			||||||
 | 
								this.memChart.updateSeries([{
 | 
				
			||||||
 | 
									data: stats.map((x, i) => ({ x: i, y: (x.mem.used / x.mem.total) }))
 | 
				
			||||||
 | 
								}]);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mounted() {
 | 
						mounted() {
 | 
				
			||||||
		this.connection.on('stats', this.onStats);
 | 
							this.connection.on('stats', this.onStats);
 | 
				
			||||||
		this.connection.on('statsLog', this.onStatsLog);
 | 
							this.connection.on('statsLog', this.onStatsLog);
 | 
				
			||||||
| 
						 | 
					@ -81,27 +40,75 @@ export default Vue.extend({
 | 
				
			||||||
			id: Math.random().toString().substr(2, 8),
 | 
								id: Math.random().toString().substr(2, 8),
 | 
				
			||||||
			length: 200
 | 
								length: 200
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const chartOpts = {
 | 
				
			||||||
 | 
								chart: {
 | 
				
			||||||
 | 
									type: 'area',
 | 
				
			||||||
 | 
									height: 300,
 | 
				
			||||||
 | 
									animations: {
 | 
				
			||||||
 | 
										dynamicAnimation: {
 | 
				
			||||||
 | 
											enabled: false
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
 | 
									toolbar: {
 | 
				
			||||||
 | 
										show: false
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								dataLabels: {
 | 
				
			||||||
 | 
									enabled: false
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								grid: {
 | 
				
			||||||
 | 
									clipMarkers: false,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								stroke: {
 | 
				
			||||||
 | 
									curve: 'straight',
 | 
				
			||||||
 | 
									width: 2
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								series: [{
 | 
				
			||||||
 | 
									data: []
 | 
				
			||||||
 | 
								}],
 | 
				
			||||||
 | 
								xaxis: {
 | 
				
			||||||
 | 
									type: 'numeric',
 | 
				
			||||||
 | 
									labels: {
 | 
				
			||||||
 | 
										show: false
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								yaxis: {
 | 
				
			||||||
 | 
									show: false,
 | 
				
			||||||
 | 
									min: 0,
 | 
				
			||||||
 | 
									max: 1
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.cpuChart = new ApexCharts(this.$refs.cpu, Object.assign({}, chartOpts, {
 | 
				
			||||||
 | 
								title: {
 | 
				
			||||||
 | 
									text: 'CPU'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}));
 | 
				
			||||||
 | 
							this.memChart = new ApexCharts(this.$refs.mem, Object.assign({}, chartOpts, {
 | 
				
			||||||
 | 
								title: {
 | 
				
			||||||
 | 
									text: 'MEM'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.cpuChart.render();
 | 
				
			||||||
 | 
							this.memChart.render();
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	beforeDestroy() {
 | 
						beforeDestroy() {
 | 
				
			||||||
		this.connection.off('stats', this.onStats);
 | 
							this.connection.off('stats', this.onStats);
 | 
				
			||||||
		this.connection.off('statsLog', this.onStatsLog);
 | 
							this.connection.off('statsLog', this.onStatsLog);
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	methods: {
 | 
						methods: {
 | 
				
			||||||
		onStats(stats) {
 | 
							onStats(stats) {
 | 
				
			||||||
			this.stats.push(stats);
 | 
								this.stats.push(stats);
 | 
				
			||||||
			if (this.stats.length > 200) this.stats.shift();
 | 
								if (this.stats.length > 200) this.stats.shift();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			const cpuPolylinePoints = this.stats.map((s, i) => [this.viewBoxX - ((this.stats.length - 1) - i), (1 - s.cpu_usage) * this.viewBoxY]);
 | 
					 | 
				
			||||||
			const memPolylinePoints = this.stats.map((s, i) => [this.viewBoxX - ((this.stats.length - 1) - i), (1 - (s.mem.used / s.mem.total)) * this.viewBoxY]);
 | 
					 | 
				
			||||||
			this.cpuPolylinePoints = cpuPolylinePoints.map(xy => `${xy[0]},${xy[1]}`).join(' ');
 | 
					 | 
				
			||||||
			this.memPolylinePoints = memPolylinePoints.map(xy => `${xy[0]},${xy[1]}`).join(' ');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			this.cpuPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${this.viewBoxY} ${this.cpuPolylinePoints} ${this.viewBoxX},${this.viewBoxY}`;
 | 
					 | 
				
			||||||
			this.memPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${this.viewBoxY} ${this.memPolylinePoints} ${this.viewBoxX},${this.viewBoxY}`;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			this.cpuP = (stats.cpu_usage * 100).toFixed(0);
 | 
								this.cpuP = (stats.cpu_usage * 100).toFixed(0);
 | 
				
			||||||
			this.memP = (stats.mem.used / stats.mem.total * 100).toFixed(0);
 | 
								this.memP = (stats.mem.used / stats.mem.total * 100).toFixed(0);
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onStatsLog(statsLog) {
 | 
							onStatsLog(statsLog) {
 | 
				
			||||||
			statsLog.reverse().forEach(stats => this.onStats(stats));
 | 
								statsLog.reverse().forEach(stats => this.onStats(stats));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -111,27 +118,17 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style lang="stylus" scoped>
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
.zyknedwtlthezamcjlolyusmipqmjgxz
 | 
					.zyknedwtlthezamcjlolyusmipqmjgxz
 | 
				
			||||||
	> svg
 | 
						display flex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> div
 | 
				
			||||||
		display block
 | 
							display block
 | 
				
			||||||
		width 50%
 | 
							flex 1
 | 
				
			||||||
		float left
 | 
							padding 32px
 | 
				
			||||||
 | 
							box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
 | 
				
			||||||
 | 
							background var(--face)
 | 
				
			||||||
 | 
							border-radius 8px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		&:first-child
 | 
							&:first-child
 | 
				
			||||||
			padding-right 5px
 | 
								margin-right 16px
 | 
				
			||||||
 | 
					 | 
				
			||||||
		&:last-child
 | 
					 | 
				
			||||||
			padding-left 5px
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		> text
 | 
					 | 
				
			||||||
			font-size 10px
 | 
					 | 
				
			||||||
			fill var(--chartCaption)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> tspan
 | 
					 | 
				
			||||||
				opacity 0.5
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	&:after
 | 
					 | 
				
			||||||
		content ""
 | 
					 | 
				
			||||||
		display block
 | 
					 | 
				
			||||||
		clear both
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,34 +1,54 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="obdskegsannmntldydackcpzezagxqfy">
 | 
					<div class="obdskegsannmntldydackcpzezagxqfy">
 | 
				
			||||||
	<div v-if="stats" class="stats">
 | 
						<div v-if="stats" class="stats">
 | 
				
			||||||
 | 
							<div>
 | 
				
			||||||
			<div>
 | 
								<div>
 | 
				
			||||||
				<div>%fa:user%</div>
 | 
									<div>%fa:user%</div>
 | 
				
			||||||
				<div>
 | 
									<div>
 | 
				
			||||||
				<span>%i18n:@original-users%</span>
 | 
										<span>%i18n:@accounts%</span>
 | 
				
			||||||
				<b>{{ stats.originalUsersCount | number }}</b>
 | 
										<b class="primary">{{ stats.originalUsersCount | number }}</b>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
 | 
								<div>
 | 
				
			||||||
 | 
									<span>%fa:home% %i18n:@this-instance%</span>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div>
 | 
				
			||||||
			<div>
 | 
								<div>
 | 
				
			||||||
				<div>%fa:pencil-alt%</div>
 | 
									<div>%fa:pencil-alt%</div>
 | 
				
			||||||
				<div>
 | 
									<div>
 | 
				
			||||||
				<span>%i18n:@original-notes%</span>
 | 
										<span>%i18n:@notes%</span>
 | 
				
			||||||
				<b>{{ stats.originalNotesCount | number }}</b>
 | 
										<b class="primary">{{ stats.originalNotesCount | number }}</b>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
 | 
								<div>
 | 
				
			||||||
 | 
									<span>%fa:home% %i18n:@this-instance%</span>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div>
 | 
				
			||||||
			<div>
 | 
								<div>
 | 
				
			||||||
				<div>%fa:user%</div>
 | 
									<div>%fa:user%</div>
 | 
				
			||||||
				<div>
 | 
									<div>
 | 
				
			||||||
				<span>%i18n:@all-users%</span>
 | 
										<span>%i18n:@accounts%</span>
 | 
				
			||||||
					<b>{{ stats.usersCount | number }}</b>
 | 
										<b>{{ stats.usersCount | number }}</b>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
 | 
								<div>
 | 
				
			||||||
 | 
									<span>%fa:globe% %i18n:@federated%</span>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div>
 | 
				
			||||||
			<div>
 | 
								<div>
 | 
				
			||||||
				<div>%fa:pencil-alt%</div>
 | 
									<div>%fa:pencil-alt%</div>
 | 
				
			||||||
				<div>
 | 
									<div>
 | 
				
			||||||
				<span>%i18n:@all-notes%</span>
 | 
										<span>%i18n:@notes%</span>
 | 
				
			||||||
					<b>{{ stats.notesCount | number }}</b>
 | 
										<b>{{ stats.notesCount | number }}</b>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
 | 
								<div>
 | 
				
			||||||
 | 
									<span>%fa:globe% %i18n:@federated%</span>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<div class="cpu-memory">
 | 
						<div class="cpu-memory">
 | 
				
			||||||
| 
						 | 
					@ -78,17 +98,22 @@ export default Vue.extend({
 | 
				
			||||||
		margin-bottom 16px
 | 
							margin-bottom 16px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> div
 | 
							> div
 | 
				
			||||||
			display flex
 | 
					 | 
				
			||||||
			align-items center
 | 
					 | 
				
			||||||
			flex 1
 | 
								flex 1
 | 
				
			||||||
			max-width 300px
 | 
								max-width 300px
 | 
				
			||||||
			margin-right 16px
 | 
								margin-right 16px
 | 
				
			||||||
			text-align center
 | 
					 | 
				
			||||||
			color var(--text)
 | 
								color var(--text)
 | 
				
			||||||
			box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
 | 
								box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
 | 
				
			||||||
			background var(--face)
 | 
								background var(--face)
 | 
				
			||||||
			border-radius 8px
 | 
								border-radius 8px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&:last-child
 | 
				
			||||||
 | 
									margin-right 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> div:first-child
 | 
				
			||||||
 | 
									display flex
 | 
				
			||||||
 | 
									align-items center
 | 
				
			||||||
 | 
									text-align center
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				&:last-child
 | 
									&:last-child
 | 
				
			||||||
					margin-right 0
 | 
										margin-right 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,16 +127,24 @@ export default Vue.extend({
 | 
				
			||||||
					text-align right
 | 
										text-align right
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					> span
 | 
										> span
 | 
				
			||||||
 | 
											font-size 70%
 | 
				
			||||||
						opacity 0.7
 | 
											opacity 0.7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					> b
 | 
										> b
 | 
				
			||||||
						display block
 | 
											display block
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											&.primary
 | 
				
			||||||
 | 
												color var(--primary)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> div:last-child
 | 
				
			||||||
 | 
									padding 6px 16px
 | 
				
			||||||
 | 
									border-top solid 1px #eee
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> span
 | 
				
			||||||
 | 
										font-size 70%
 | 
				
			||||||
 | 
										opacity 0.7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .cpu-memory
 | 
						> .cpu-memory
 | 
				
			||||||
		margin-bottom 16px
 | 
							margin-bottom 16px
 | 
				
			||||||
		padding 32px
 | 
					 | 
				
			||||||
		box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
 | 
					 | 
				
			||||||
		background var(--face)
 | 
					 | 
				
			||||||
		border-radius 8px
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue