Skip to content

Commit

Permalink
Merge branch 'master' into pierre-netbox-supported-versions-minor
Browse files Browse the repository at this point in the history
  • Loading branch information
MathieuRA authored Sep 23, 2024
2 parents 7f39451 + 381c83d commit edfa903
Show file tree
Hide file tree
Showing 184 changed files with 3,292 additions and 2,847 deletions.
10 changes: 6 additions & 4 deletions @vates/parse-duration/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ exports.parseDuration = value => {
if (typeof value === 'number') {
return value
}
const duration = ms(value)
if (duration === undefined) {
throw new TypeError(`not a valid duration: ${value}`)
if (typeof value === 'string' && value !== '') {
const duration = ms(value)
if (duration !== undefined) {
return duration
}
}
return duration
throw new TypeError(`not a valid duration: ${value}`)
}
22 changes: 22 additions & 0 deletions @vates/parse-duration/index.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { describe, it } from 'node:test'
import { parseDuration } from '@vates/parse-duration'
import assert from 'node:assert/strict'

describe('parseDuration()', () => {
it('should parse string', () => {
const input = '2 days'
const expected = 172800000
assert.strictEqual(parseDuration(input), expected)
})

it('should return its input if already a number', () => {
const input = 172800000
assert.strictEqual(parseDuration(input), input)
})

for (const input of [undefined, '', 'invalid duration']) {
it('should throw an error for ' + input, () => {
assert.throws(() => parseDuration(input), { message: `not a valid duration: ${input}` })
})
}
})
3 changes: 2 additions & 1 deletion @vates/parse-duration/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"ms": "^2.1.2"
},
"scripts": {
"postversion": "npm publish --access public"
"postversion": "npm publish --access public",
"test": "node --test"
}
}
4 changes: 0 additions & 4 deletions @xen-orchestra/backups/_incrementalVm.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import ignoreErrors from 'promise-toolbox/ignoreErrors'
import { asyncMap } from '@xen-orchestra/async-map'
import { CancelToken } from 'promise-toolbox'
import { compareVersions } from 'compare-versions'
import { createVhdStreamWithLength } from 'vhd-lib'
import { defer } from 'golike-defer'

import { cancelableMap } from './_cancelableMap.mjs'
Expand Down Expand Up @@ -227,9 +226,6 @@ export const importIncrementalVm = defer(async function importIncrementalVm(
if (typeof stream === 'function') {
stream = await stream()
}
if (stream.length === undefined) {
stream = await createVhdStreamWithLength(stream)
}
await xapi.setField('VDI', vdi.$ref, 'name_label', `[Importing] ${vdiRecords[id].name_label}`)
await vdi.$importContent(stream, { cancelToken, format: 'vhd' })
await xapi.setField('VDI', vdi.$ref, 'name_label', vdiRecords[id].name_label)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ export const AbstractXapi = class AbstractXapiVmBackupRunner extends Abstract {
await this._xapi.VDI_dataDestroy(vdiRef)
Task.info(`Snapshot data has been deleted`, { vdiRef })
} catch (error) {
Task.warning(`Couldn't deleted snapshot data`, { error, vdiRef })
Task.warning(`Couldn't delete snapshot data`, { error, vdiRef })
}
}
}
Expand Down
211 changes: 2 additions & 209 deletions @xen-orchestra/lite/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,213 +5,6 @@
- `yarn`
- `yarn dev`

## Conventions
## Guidelines

### File names

| Type | Format | Exemple |
| ---------- | ---------------------------------------- | ----------------------------------- |
| Component | `components/<PascalCase>.vue` | `components/FooBar.vue` |
| View | `views/<PascalCase>View.vue` | `views/FooBarView.vue` |
| Composable | `composables/<kebab-case>.composable.ts` | `composables/foo-bar.composable.ts` |
| Store | `stores/<kebab-case>.store.ts` | `stores/foo-bar.store.ts` |
| Other | `libs/<kebab-case>.ts` | `libs/foo-bar.ts` |

For components and views, prepend the subdirectories names to the resulting filename.

Example: `components/foo/bar/FooBarBaz.vue`

### Vue Components

Use Vue Single File Components (`*.vue`).

Insert blocks in the following order: `template`, `script` then `style`.

#### Template

Use HTML.

If your component only has one root element, add the component name as a class.

```vue
<!-- MyComponent.vue -->
<template>
<div class="my-component">...</div>
</template>
```

#### Script

Use composition API + TypeScript + `setup` attribute (`<script lang="ts" setup>`).

Note: When reading Vue official doc, don't forget to set "API Preference" toggle (in the upper left) on "Composition".

```vue
<script lang="ts" setup>
import { computed, ref } from 'vue'
const props = defineProps<{
greetings: string
}>()
const firstName = ref('')
const lastName = ref('')
const fullName = computed(() => `${props.greetings} ${firstName.value} ${lastName.value}`)
</script>
```

#### CSS

Always use `scoped` attribute (`<style scoped>`).

Nested rules are allowed.

Vue variables can be interpolated with `v-bind`.

```vue
<script lang="ts" setup>
import { ref } from 'vue'
const fontSize = ref('2rem')
</script>
<style scoped>
.my-item {
.nested {
font-size: v-bind(fontSize);
}
}
</style>
```

### Icons

This project is using Font Awesome 6 Free.

Icons can be displayed with the `UiIcon` component.

Passing `undefined` as `icon` prop will disable the component (no need to use an additional `v-if` condition).

Use the `busy` prop to display a loader icon.

```vue
<template>
<div>
<UiIcon :icon="faDisplay" />
</div>
</template>
<script lang="ts" setup>
import UiIcon from '@/components/ui/icon/UiIcon.vue'
import { faDisplay } from '@fortawesome/free-solid-svg-icons'
</script>
```

#### Font weight <=> Style name

Here is the equivalent between font weight and style name.

| Style name | Font weight |
| ---------- | ----------- |
| Solid | 900 |
| Regular | 400 |

### CSS

Always use `rem` unit (`1rem` = `10px`)

### Store

Use Pinia store with setup function.

State are `ref`

Getters are `computed`

Actions/Mutations are simple functions

#### Naming convention

For a `foobar` store, create a `store/foobar.store.ts` then use `defineStore('foobar', setupFunc)`

#### Example

```typescript
import { computed, ref } from 'vue'

export const useFoobarStore = defineStore('foobar', () => {
const aStateVar = ref(0)
const otherStateVar = ref(0)
const aGetter = computed(() => aStateVar.value * 2)
const anAction = () => (otherStateVar.value += 10)

return {
aStateVar,
otherStateVar,
aGetter,
anAction,
}
})
```

### I18n

Internationalization of the app is done with [Vue-i18n](https://vue-i18n.intlify.dev/).

Locale files are located in `src/locales` directory.

Source of truth is `en-US.json` file.

To quickly check if there are missing translations in other locale files, open `main.ts` and check the `messages`
property of `createI18n()` for TypeScript error.

#### Example

```json
{
"hello": "Hello",
"hello_name": "Hello {name}",
"hello_linked": "@:hello_name how are you?",
"hello_plural": "No hello | Hello to you | Hello to {count} persons"
}
```

```html
<!-- String -->

<p>{{ $t("hello") }}</p>
<!-- Hello -->
<p>{{ $t("hello_name", { name: "World" }) }}</p>
<!-- Hello World -->
<p>{{ $t("hello_linked", { name: "World" }) }}</p>
<!-- Hello World how are you? -->
<p>{{ $tc("hello_plural", 0) }}</p>
<!-- No hello -->
<p>{{ $tc("hello_plural", 1) }}</p>
<!-- Hello to you -->
<p>{{ $tc("hello_plural", 4) }}</p>
<!-- Hello to 4 persons -->

<!-- Date and time -->

<p>{{ $d(date, "date_short") }}</p>
<!-- 9/10/2022 -->
<p>{{ $d(date, "date_medium") }}</p>
<!-- Sep 10, 2022 -->
<p>{{ $d(date, "date_long") }}</p>
<!-- September 10, 2022 -->
<p>{{ $d(date, "datetime_short") }}</p>
<!-- 9/10/2022, 06:30 PM -->
<p>{{ $d(date, "datetime_medium") }}</p>
<!-- Sep 10, 2022, 06:30 PM -->
<p>{{ $d(date, "datetime_long") }}</p>
<!-- September 10, 2022 at 06:30 PM -->
<p>{{ $d(date, "time") }}</p>
<!-- 06:30 PM -->

<!-- Number -->

<p>{{ $n(1234567.898765) }}</p>
<!-- 1,234,567.899 -->
```
Please follow the guidelines from the `@xen-orchestra/web-core/docs/guidelines` directory.
2 changes: 1 addition & 1 deletion @xen-orchestra/lite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"postcss-nested": "^6.0.1",
"typescript": "~5.3.3",
"vite": "^5.0.11",
"vue": "^3.4.13",
"vue": "~3.4.13",
"vue-echarts": "^6.6.8",
"vue-i18n": "^9.9.0",
"vue-router": "^4.4.0",
Expand Down
2 changes: 1 addition & 1 deletion @xen-orchestra/lite/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ useUnreachableHosts()
overflow: auto;
flex: 1;
height: calc(100vh - 5.5rem);
background-color: var(--background-color-secondary);
background-color: var(--color-neutral-background-secondary);
&.no-ui {
height: 100vh;
Expand Down
14 changes: 7 additions & 7 deletions @xen-orchestra/lite/src/components/AccountButton.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<MenuList placement="bottom-end" shadow>
<MenuList placement="bottom-end" border>
<template #trigger="{ open, isOpen }">
<button type="button" :class="{ active: isOpen }" class="account-button" @click="open">
<UiIcon :icon="faCircleUser" class="user-icon" />
Expand Down Expand Up @@ -51,14 +51,14 @@ const openSettings = () => router.push({ name: 'settings' })
display: flex;
align-items: center;
padding: 1rem;
color: var(--color-grey-100);
color: var(--color-neutral-txt-primary);
border: none;
border-radius: 0.8rem;
background-color: var(--background-color-secondary);
background-color: var(--color-neutral-background-secondary);
gap: 0.8rem;
&:disabled {
color: var(--color-grey-500);
color: var(--color-neutral-border);
}
&:not(:disabled) {
Expand All @@ -67,12 +67,12 @@ const openSettings = () => router.push({ name: 'settings' })
&:hover,
&:active,
&.active {
background-color: var(--background-color-primary);
background-color: var(--color-neutral-background-primary);
}
&:active,
&.active {
color: var(--color-purple-base);
color: var(--color-normal-txt-base);
}
}
}
Expand All @@ -86,6 +86,6 @@ const openSettings = () => router.push({ name: 'settings' })
}
.menu-item-logout {
color: var(--color-red-base);
color: var(--color-danger-txt-base);
}
</style>
4 changes: 2 additions & 2 deletions @xen-orchestra/lite/src/components/AppHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ const { trigger: navigationTrigger } = storeToRefs(navigationStore)
justify-content: space-between;
height: 5.5rem;
padding: 1rem;
border-bottom: 0.1rem solid var(--color-grey-500);
background-color: var(--background-color-secondary);
border-bottom: 0.1rem solid var(--color-neutral-border);
background-color: var(--color-neutral-background-secondary);
img {
width: 4rem;
Expand Down
Loading

0 comments on commit edfa903

Please sign in to comment.