diff --git a/.storybook/preview-head.html b/.storybook/preview-head.html index faecbe834b..0339b8d32b 100644 --- a/.storybook/preview-head.html +++ b/.storybook/preview-head.html @@ -1 +1,19 @@ + + + diff --git a/package-lock.json b/package-lock.json index ed7ff911b2..d9b6bf57e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36239,6 +36239,7 @@ "@material/mwc-checkbox": "^0.27.0", "@material/mwc-circular-progress": "^0.27.0", "@material/mwc-formfield": "^0.27.0", + "@material/mwc-icon": "^0.27.0", "@material/mwc-list": "^0.27.0", "@material/mwc-menu": "^0.27.0", "@material/mwc-radio": "^0.27.0", @@ -36641,14 +36642,6 @@ "lit-html": "^2.8.0" } }, - "server_manager/node_modules/@material/mwc-icon/node_modules/lit-html": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.8.0.tgz", - "integrity": "sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q==", - "dependencies": { - "@types/trusted-types": "^2.0.2" - } - }, "server_manager/node_modules/@material/mwc-line-ripple": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/@material/mwc-line-ripple/-/mwc-line-ripple-0.27.0.tgz", @@ -42335,6 +42328,7 @@ "@material/mwc-checkbox": "^0.27.0", "@material/mwc-circular-progress": "^0.27.0", "@material/mwc-formfield": "^0.27.0", + "@material/mwc-icon": "^0.27.0", "@material/mwc-list": "^0.27.0", "@material/mwc-menu": "^0.27.0", "@material/mwc-radio": "^0.27.0", @@ -42737,14 +42731,6 @@ "lit-element": "^3.3.0", "lit-html": "^2.8.0" } - }, - "lit-html": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.8.0.tgz", - "integrity": "sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q==", - "requires": { - "@types/trusted-types": "^2.0.2" - } } } }, diff --git a/server_manager/package.json b/server_manager/package.json index f2e79389d2..88428bb2c2 100644 --- a/server_manager/package.json +++ b/server_manager/package.json @@ -21,6 +21,7 @@ "@material/mwc-checkbox": "^0.27.0", "@material/mwc-circular-progress": "^0.27.0", "@material/mwc-formfield": "^0.27.0", + "@material/mwc-icon": "^0.27.0", "@material/mwc-list": "^0.27.0", "@material/mwc-menu": "^0.27.0", "@material/mwc-radio": "^0.27.0", diff --git a/server_manager/www/stories.ts b/server_manager/www/stories.ts deleted file mode 100644 index e7f8387534..0000000000 --- a/server_manager/www/stories.ts +++ /dev/null @@ -1,8 +0,0 @@ - -import {html} from 'lit'; - -export default { - title: 'Manager/TODO', -}; - -export const Example = () => html`TODO: Write our first manager story!`; diff --git a/server_manager/www/views/server_view/server_stat_card/index.ts b/server_manager/www/views/server_view/server_stat_card/index.ts new file mode 100644 index 0000000000..da08005cd3 --- /dev/null +++ b/server_manager/www/views/server_view/server_stat_card/index.ts @@ -0,0 +1,92 @@ +/** + * Copyright 2024 The Outline Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import '@material/mwc-icon'; + +import {css, html, LitElement} from 'lit'; +import {customElement, property} from 'lit/decorators.js'; + +@customElement('server-stat-card') +export class ServerStatCard extends LitElement { + @property({type: Number}) value: number; + @property({type: String}) icon: string; + @property({type: String}) name: string; + @property({type: String}) units: string; + + static styles = [ + css` + :host { + background: var(--server-background); + border-radius: 0.25rem; + box-sizing: border-box; + container-name: conceal-name conceal-units; + container-type: size; + display: flex; + flex-direction: column; + gap: 0.25rem; + height: 100%; + justify-content: space-between; + overflow: hidden; + padding: 2rem; + width: 100%; + } + + .data, + .data-value, + .name { + all: initial; + font-family: "Roboto", sans-serif; + } + + mwc-icon, + .data, + .data-value, + .name { + color: var(--server-foreground); + } + + .data-value { + color: var(--server-highlight); + font-size: 3rem; + font-weight: 300; + } + + @container conceal-name (max-height: 150px) { + .name { + display: none; + } + } + + @container conceal-units (max-width: 150px) { + .data-units { + display: none; + } + } + `, + ]; + + render() { + return html` + ${this.icon} +

+ ${this.value} + ${this.units} +

+

+ ${this.name} +

`; + } +} diff --git a/server_manager/www/views/server_view/server_stat_card/stories.ts b/server_manager/www/views/server_view/server_stat_card/stories.ts new file mode 100644 index 0000000000..746324782c --- /dev/null +++ b/server_manager/www/views/server_view/server_stat_card/stories.ts @@ -0,0 +1,37 @@ +/** + * Copyright 2024 The Outline Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {html} from 'lit'; + +import './index'; +import {ServerStatCard} from './index'; + +export default { + title: 'Manager/Server View/Server Stat Card', + component: 'server-stats-card', + args: { + icon: "swap_horiz", + name: "Data transferred / last 30 days", + units: "Bytes", + value: 0 + } +}; + +export const Example = ({icon, name, value, units}: ServerStatCard) => html` +
+ +
+`; diff --git a/server_manager/www/views/server_view/server_stat_grid/index.ts b/server_manager/www/views/server_view/server_stat_grid/index.ts new file mode 100644 index 0000000000..b7908b55be --- /dev/null +++ b/server_manager/www/views/server_view/server_stat_grid/index.ts @@ -0,0 +1,62 @@ +/** + * Copyright 2024 The Outline Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {css, html, LitElement} from 'lit'; +import {customElement, property} from 'lit/decorators.js'; +import {styleMap} from 'lit/directives/style-map.js'; + +import { ServerStatCard } from '../server_stat_card'; + +@customElement("server-stat-grid") +export class ServerStatGrid extends LitElement { + @property({ type: Array }) stats: Array; + @property({ type: Number }) columns: number; + @property({ type: Number }) rows: number; + + static styles = [ + css` + :host, + article { + width: 100%; + height: 100%; + } + + article { + display: grid; + gap: 0.25rem; + } + `, + ]; + + render() { + return html` +
+ ${this.stats.map(({ name, value, units, icon, column: gridColumn, row: gridRow }) => html` + + + `)} +
+ `; + } +} \ No newline at end of file diff --git a/server_manager/www/views/server_view/server_stat_grid/stories.ts b/server_manager/www/views/server_view/server_stat_grid/stories.ts new file mode 100644 index 0000000000..451d179334 --- /dev/null +++ b/server_manager/www/views/server_view/server_stat_grid/stories.ts @@ -0,0 +1,65 @@ +/** + * Copyright 2024 The Outline Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {html} from 'lit'; + +import './index'; +import {ServerStatGrid} from './index'; + +export default { + title: 'Manager/Server View/Server Stat Grid', + component: 'server-stats-grid', + args: { + columns: 3, + rows: 2, + stats: [ + { + icon: "swap_horiz", + name: "Data transferred / last 30 days", + units: "GB", + value: 2345 + }, + { + icon: "timer", + name: "Average time spent across clients", + units: "Client Hours / Hour", + value: 83.7, + column: "3", + row: "1 / 3", + }, + { + icon: "key", + name: "Server access", + units: "Keys", + value: 155, + row: "1", + column: "1 / 3" + }, + { + icon: "cloud", + name: "Allowance Used", + units: "/ 15 TB", + value: 12.3 + } + ] + } +}; + +export const Example = ({stats, columns, rows}: ServerStatGrid) => html` +
+ +
+`;