Skip to content
Snippets Groups Projects
Commit 3f8216d2 authored by Anthony Gautreau's avatar Anthony Gautreau
Browse files

Init

parents
Branches
No related tags found
No related merge requests found
> 1%
last 2 versions
not dead
not ie 11
[*.{js,jsx,ts,tsx,vue}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# Unicaen-vue-mail [WIP]
Cette bibliothèques à pour but de fournir un front Vue3 à la bibliothèques [unicaen-mail](https://git.unicaen.fr/lib/unicaen/mail).
## Install
1. Ajouter le registry npm d'unicaen : https://kverdaccio.unicaen.fr/
2. ```bash
npm install unicaen-vue-mail
```
3. ```js
<script setup>
import Mail from 'unicaen-vue-mail';
</script>
```
```js
<Mail :title="title" :mails="mails" :params="params" />
```
## Outils associés
- [Vuetify](https://vuetifyjs.com/)
- [Vite](https://vitejs.dev/)
- [Typescript](https://www.typescriptlang.org/)
## Dev
#### Starting the Development Server
To start the development server with hot-reload, run the following command. The server will be accessible at [http://localhost:3000](http://localhost:3000):
```bash
npm run dev
```
#### Building for Production
To build your project for production, use:
```bash
npm run build
```
Once the build process is completed, your application will be ready for deployment in a production environment.
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {}
declare module 'vue' {
export interface GlobalComponents {
Filter: typeof import('./src/components/Filter.vue')['default']
HelloWorld: typeof import('./src/components/HelloWorld.vue')['default']
Mail: typeof import('./src/components/Mail.vue')['default']
TableMail: typeof import('./src/components/TableMail.vue')['default']
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Welcome to Vuetify 3</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
This diff is collapsed.
{
"name": "unicaen-vue-mail",
"version": "0.2.0",
"description": "Unicaen Vue Mail",
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview",
"publish": "npm publish --registry https://kverdaccio.unicaen.fr/"
},
"dependencies": {
"moment": "^2.30.1",
"roboto-fontface": "*",
"vue": "^3.4.21",
"vuetify": "^3.5.8"
},
"devDependencies": {
"@babel/types": "^7.24.0",
"@fortawesome/fontawesome-svg-core": "^6.5.1",
"@fortawesome/free-regular-svg-icons": "^6.5.1",
"@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/vue-fontawesome": "^3.0.6",
"@types/node": "^20.11.25",
"@vitejs/plugin-vue": "^5.0.4",
"sass": "^1.71.1",
"typescript": "^5.4.2",
"unplugin-fonts": "^1.1.1",
"unplugin-vue-components": "^0.26.0",
"vite": "^5.1.5",
"vite-plugin-vuetify": "^2.0.3",
"vue-tsc": "^2.0.6"
}
}
public/favicon.ico

15 KiB

<template>
<v-app>
<v-container >
<Mail :title="props.title" :mails="props.mails" :params="props.params" />
</v-container>
</v-app>
</template>
<script setup lang="ts">
import Mail from './components/Mail.vue';
const props = {
title: 'Mail',
mails: [
{
destinataires: 'anthony.gautreau@unicaen.fr',
dateEnvoi: '2022-01-01 02:00:00',
statusEnvoi: 'SUCCESS',
sujet: 'Test',
motsClefs: 'test'
},
],
params: {}
}
</script>
src/assets/logo.png

11.7 KiB

<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M261.126 140.65L164.624 307.732L256.001 466L377.028 256.5L498.001 47H315.192L261.126 140.65Z" fill="#1697F6"/>
<path d="M135.027 256.5L141.365 267.518L231.64 111.178L268.731 47H256H14L135.027 256.5Z" fill="#AEDDFF"/>
<path d="M315.191 47C360.935 197.446 256 466 256 466L164.624 307.732L315.191 47Z" fill="#1867C0"/>
<path d="M268.731 47C76.0026 47 141.366 267.518 141.366 267.518L268.731 47Z" fill="#7BC6FF"/>
</svg>
<template>
<v-col>
<v-select
prepend-icon="search"
label="Status"
v-model="filterStatus"
:items="['PENDING','SUCCESS','FAILED', 'NOT SENT']"
chips
multiple
></v-select>
</v-col>
<v-col>
<v-select
prepend-icon="calendar"
label="Historique"
item-title="text"
v-model="filterHistory"
item-value="value"
:items="[
{
text: '<1 mois',
value: 1
},
{
text: '<3 mois',
value: 3
},
{
text: '<6 mois',
value: 6
}
,
{
text: '<1 an',
value: 12
}
,
{
text: '>1 an',
value: 0
}
]"
></v-select>
</v-col>
<v-col>
<v-select
prepend-icon="tag"
label="Mots clés"
v-model="filterMotsClefs"
:items="motsClefsUniques"
>
</v-select>
</v-col>
</template>
<script setup>
import { ref, defineModel, defineProps, computed } from 'vue';
const props = defineProps({
motsClefsUniques: Object
});
const filterHistory = defineModel('filterHistory')
const filterStatus = defineModel('filterStatus')
const filterMotsClefs = defineModel('filterMotsClefs')
</script>
\ No newline at end of file
<template>
<h1 class="page-header">Gestion des mails</h1>
<v-btn prepend-icon="envelope">
Envoi d'un mail de testtt
</v-btn>
<v-card
prepend-icon="filter"
title="Filtre des courriers électroniques"
>
<v-row>
<Filter
v-model:filter-history="filterHistory"
v-model:filter-status="filterStatus"
v-model:filter-mots-clefs="filterMotsClefs"
:mots-clefs-uniques="motsClefsUniques"
></Filter>
</v-row>
</v-card>
<v-card
prepend-icon="list"
title="Liste des mails"
>
</v-card>
<TableMail :mails="mailFiltered" />
</template>
<script setup>
import TableMail from "./TableMail.vue";
import Filter from "./Filter.vue";
import { ref, computed } from 'vue';
import moment from 'moment';
import { inject } from 'vue'
const options = inject('options')
const props = defineProps({
title: String,
mails: Object,
params: Object
});
const filterHistory = ref(1)
const filterStatus = ref([])
const filterMotsClefs = ref('Tous')
const mailFiltered = computed(() => {
return props.mails.filter(mail => {
const mailDate = moment(mail.dateEnvoi);
const now = moment();
const diffMonths = now.diff(mailDate, 'months', true);
const matchHistory = (filterHistory.value > 0) ? diffMonths <= filterHistory.value : true;
const matchStatus = (filterStatus.value.length) ? filterStatus.value.includes(mail.statusEnvoi) : true;
const matchMotsClefs = (filterMotsClefs.value !== 'Tous') ? mail.motsClefs.includes(filterMotsClefs.value) : true;
return matchHistory && matchStatus && matchMotsClefs;
});
})
const motsClefsUniques = computed(() => {
let allMotsClefs = props.mails.flatMap(mail => mail.motsClefs.split(options.motsClefsSeparateur));
allMotsClefs = Array.from(new Set(allMotsClefs))
// add empty string to the list
allMotsClefs.unshift('Tous');
return allMotsClefs;
});
</script>
<style scoped>
</style>
# Components
Vue template files in this folder are automatically imported.
## 🚀 Usage
Importing is handled by [unplugin-vue-components](https://github.com/unplugin/unplugin-vue-components). This plugin automatically imports `.vue` files created in the `src/components` directory, and registers them as global components. This means that you can use any component in your application without having to manually import it.
The following example assumes a component located at `src/components/MyComponent.vue`:
```vue
<template>
<div>
<MyComponent />
</div>
</template>
<script lang="ts" setup>
//
</script>
```
When your template is rendered, the component's import will automatically be inlined, which renders to this:
```vue
<template>
<div>
<MyComponent />
</div>
</template>
<script lang="ts" setup>
import MyComponent from '@/components/MyComponent.vue'
</script>
```
<template>
<v-data-table
:items="mails"
:headers="headers"
density="comfortable"
>
<template v-slot:item.destinataires="{ item }">
<ul v-for="(destinataire, index) in item.destinataires.split(',')"
:key="destinataire">
<li>{{destinataire}}</li>
<li v-if="(index === (item.destinataires.split(',').length-1)) && item.destinatairesInitials">
<v-chip color="badge">
Initialement: {{item.destinatairesInitials}}
</v-chip>
</li>
</ul>
</template>
<template v-slot:item.dateEnvoi="{ item }">
{{ moment(item.dateEnvoi).format('DD/MM/YYYY HH:mm') }}
</template>
<template v-slot:item.statusEnvoi="{ item }">
<v-chip :color="getColorStatus(item.statusEnvoi)">
{{ item.statusEnvoi }}
</v-chip>
</template>
<template v-slot:item.motsClefs="{ item }">
<v-chip v-for="mot in item.motsClefs.split(options.motsClefsSeparateur)" :key="mot">
{{ mot }}
</v-chip>
</template>
<template v-slot:item.actions="{ item }">
<v-dialog max-width="1000">
<template v-slot:activator="{ props: viewMailActivator }">
<v-btn icon="fa-eye" v-bind="viewMailActivator"></v-btn>
</template>
<template v-slot:default="{ isActive }">
<v-card
:title="'Affichage du mail #'+item.id"
>
<v-row no-gutters>
<v-col class="ml-2">
<dl>
<dt>Identifiant</dt>
<dd>{{ item.id }}</dd>
<dt>Statut</dt>
<dd>
<v-chip :color="getColorStatus(item.statusEnvoi)">
{{ item.statusEnvoi }}
</v-chip>
</dd>
<dt>Date d'envoi</dt>
<dd>{{ moment(item.dateEnvoi).format('DD/MM/YYYY HH:mm') }}</dd>
<dt>Logs</dt>
<dd>{{ item.logs || 'Vide' }}</dd>
<dt>Destinataires</dt>
<dd class="text-pre-wrap">
{{ addSpace(item.destinataires) }}
<div v-if="item.destinatairesInitials">
<v-chip color="badge">
Initialement: {{item.destinatairesInitials}}
</v-chip>
</div>
</dd>
<dt class="font-weight-bold">Mots clés</dt>
<dd>
<v-chip v-for="mot in item.motsClefs.split(options.motsClefsSeparateur)" :key="mot">
{{ mot }}
</v-chip>
</dd>
</dl>
</v-col>
<v-col>
<v-card variant="elevated">
<v-card-title>
<h3>{{ item.sujet }}</h3>
</v-card-title>
<v-card-text v-html="item.corps"></v-card-text>
</v-card>
</v-col>
</v-row>
</v-card>
</template>
</v-dialog>
<v-btn icon="envelope" title="Ré-envoyer le mail"></v-btn>
<v-btn icon="trash" color="error"></v-btn>
</template>
</v-data-table>
</template>
<script setup>
import moment from 'moment';
import { inject } from 'vue'
const options = inject('options')
const props = defineProps({
mails: Object
});
const headers = [
{ title: 'Destinataires', value: 'destinataires' },
{ title: 'Date d\'envoi', value: 'dateEnvoi' },
{ title: 'Statut', value: 'statusEnvoi' },
{ title: 'Sujet', value: 'sujet' },
{ title: 'Mots Clés', value: 'motsClefs' },
{ title: 'Actions', value: 'actions', align: 'end'}
]
const getColorStatus = (status) => {
switch (status) {
case 'SUCCESS':
return 'success'
case 'PENDING':
return 'info'
case 'FAILED':
return 'error'
case 'NOT SENT':
return 'warning'
default:
return 'info'
}
}
const addSpace = (str) => {
return str.split(',').join(', ')
}
</script>
<style scoped>
ul {
padding-bottom: 3px;
}
</style>
\ No newline at end of file
/**
* main.ts
*
* Bootstraps Vuetify and other plugins then mounts the App`
*/
// Plugins
import { registerPlugins } from './plugins'
// Components
import App from './App.vue'
// Composables
import { createApp } from 'vue'
const app = createApp(App)
app.provide('options', {
"motsClefsSeparateur": "||",
})
registerPlugins(app)
app.mount('#app')
# Plugins
Plugins are a way to extend the functionality of your Vue application. Use this folder for registering plugins that you want to use globally.
/**
* plugins/index.ts
*
* Automatically included in `./src/main.ts`
*/
// Plugins
import vuetify from './vuetify'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
// Types
import type { App } from 'vue'
export function registerPlugins (app: App) {
app.use(vuetify)
app.component('font-awesome-icon', FontAwesomeIcon) // Register component globally
}
/**
* plugins/vuetify.ts
*
* Framework documentation: https://vuetifyjs.com`
*/
// FontAwesome
import { aliases, fa } from 'vuetify/iconsets/fa-svg'
import { library } from '@fortawesome/fontawesome-svg-core'
import { fas } from '@fortawesome/free-solid-svg-icons'
import { far } from '@fortawesome/free-regular-svg-icons'
// Styles
import 'vuetify/styles'
library.add(fas) // Include needed solid icons
library.add(far) // Include needed regular icons
// Composables
import { createVuetify } from 'vuetify'
// https://vuetifyjs.com/en/introduction/why-vuetify/#feature-guides
export default createVuetify({
icons: {
defaultSet: 'fa',
aliases,
sets: {
fa,
},
},
theme: {
defaultTheme: 'light',
},
})
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment