master-page-vue 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -0
- package/dist/components/AppFooter.vue.d.ts +2 -0
- package/dist/components/AppHeader.vue.d.ts +6 -0
- package/dist/components/AppMenu.vue.d.ts +5 -0
- package/dist/components/MasterPage.vue.d.ts +12 -0
- package/dist/composables/useAuth.d.ts +46 -0
- package/dist/index.d.ts +15 -0
- package/dist/master-page-vue.mjs +355 -0
- package/dist/master-page-vue.umd.js +1 -0
- package/dist/models/types.d.ts +32 -0
- package/dist/style.css +1 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# master-page-vue
|
|
2
|
+
|
|
3
|
+
Master page layout with Header, Sidebar Menu and Footer for Vue 3, with OIDC authentication via `oidc-client-ts`.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install master-page-vue oidc-client-ts
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
// main.ts
|
|
15
|
+
import { createApp } from 'vue';
|
|
16
|
+
import App from './App.vue';
|
|
17
|
+
import MasterPagePlugin from 'master-page-vue';
|
|
18
|
+
|
|
19
|
+
createApp(App)
|
|
20
|
+
.use(MasterPagePlugin, {
|
|
21
|
+
oidc: {
|
|
22
|
+
authority: 'https://identity.example.com',
|
|
23
|
+
clientId: 'mi-app',
|
|
24
|
+
},
|
|
25
|
+
appTitle: 'SISPRO - Mi Aplicación',
|
|
26
|
+
})
|
|
27
|
+
.mount('#app');
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```vue
|
|
31
|
+
<!-- App.vue -->
|
|
32
|
+
<template>
|
|
33
|
+
<MasterPage>
|
|
34
|
+
<RouterView />
|
|
35
|
+
</MasterPage>
|
|
36
|
+
</template>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Config options
|
|
40
|
+
|
|
41
|
+
| Option | Type | Description |
|
|
42
|
+
|--------|------|-------------|
|
|
43
|
+
| `oidc.authority` | `string` | Identity server URL |
|
|
44
|
+
| `oidc.clientId` | `string` | OAuth client ID |
|
|
45
|
+
| `oidc.clientSecret` | `string?` | OAuth client secret |
|
|
46
|
+
| `oidc.redirectUri` | `string?` | Redirect URI after login |
|
|
47
|
+
| `oidc.postLogoutRedirectUri` | `string?` | Redirect URI after logout |
|
|
48
|
+
| `oidc.scope` | `string?` | OAuth scopes |
|
|
49
|
+
| `appTitle` | `string?` | Title shown in header |
|
|
50
|
+
| `enableFetchInterceptor` | `boolean?` | Auto-inject bearer token in fetch calls |
|
|
51
|
+
| `registerUrl` | `string?` | Registration URL |
|
|
52
|
+
|
|
53
|
+
## Composable
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { useAuth } from 'master-page-vue';
|
|
57
|
+
|
|
58
|
+
const { isAuthenticated, userProfile, menuItems, login, logout } = useAuth();
|
|
59
|
+
```
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
+
export default _default;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
2
|
+
"menu-toggle": () => any;
|
|
3
|
+
}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{
|
|
4
|
+
"onMenu-toggle"?: (() => any) | undefined;
|
|
5
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
6
|
+
export default _default;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
isOpen: boolean;
|
|
3
|
+
};
|
|
4
|
+
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
5
|
+
export default _default;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
declare var __VLS_11: {};
|
|
2
|
+
type __VLS_Slots = {} & {
|
|
3
|
+
default?: (props: typeof __VLS_11) => any;
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_component: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
6
|
+
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
7
|
+
export default _default;
|
|
8
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
9
|
+
new (): {
|
|
10
|
+
$slots: S;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { MasterPageConfig } from '../models/types';
|
|
2
|
+
export declare function useAuth(): {
|
|
3
|
+
isAuthenticated: Readonly<import("vue").Ref<boolean, boolean>>;
|
|
4
|
+
userProfile: Readonly<import("vue").Ref<{
|
|
5
|
+
readonly firstName: string;
|
|
6
|
+
readonly middleName: string;
|
|
7
|
+
readonly lastName: string;
|
|
8
|
+
readonly secondLastName: string;
|
|
9
|
+
readonly enterpriseName: string;
|
|
10
|
+
readonly displayName: string;
|
|
11
|
+
readonly email?: string | undefined;
|
|
12
|
+
readonly accessToken: string;
|
|
13
|
+
readonly rawClaims: {
|
|
14
|
+
readonly [x: string]: Readonly<unknown>;
|
|
15
|
+
};
|
|
16
|
+
} | null, {
|
|
17
|
+
readonly firstName: string;
|
|
18
|
+
readonly middleName: string;
|
|
19
|
+
readonly lastName: string;
|
|
20
|
+
readonly secondLastName: string;
|
|
21
|
+
readonly enterpriseName: string;
|
|
22
|
+
readonly displayName: string;
|
|
23
|
+
readonly email?: string | undefined;
|
|
24
|
+
readonly accessToken: string;
|
|
25
|
+
readonly rawClaims: {
|
|
26
|
+
readonly [x: string]: Readonly<unknown>;
|
|
27
|
+
};
|
|
28
|
+
} | null>>;
|
|
29
|
+
menuItems: Readonly<import("vue").Ref<readonly {
|
|
30
|
+
readonly nombre: string;
|
|
31
|
+
readonly url?: string | undefined;
|
|
32
|
+
readonly hijos?: readonly /*elided*/ any[] | undefined;
|
|
33
|
+
}[], readonly {
|
|
34
|
+
readonly nombre: string;
|
|
35
|
+
readonly url?: string | undefined;
|
|
36
|
+
readonly hijos?: readonly /*elided*/ any[] | undefined;
|
|
37
|
+
}[]>>;
|
|
38
|
+
isLoading: Readonly<import("vue").Ref<boolean, boolean>>;
|
|
39
|
+
configure: (cfg: MasterPageConfig) => void;
|
|
40
|
+
getConfig: () => MasterPageConfig;
|
|
41
|
+
login: () => void;
|
|
42
|
+
logout: () => void;
|
|
43
|
+
openAccountSettings: () => void;
|
|
44
|
+
getAccessToken: () => Promise<string | null>;
|
|
45
|
+
destroyFetchInterceptor: () => void;
|
|
46
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { App } from 'vue';
|
|
2
|
+
import type { MasterPageConfig } from './models/types';
|
|
3
|
+
import { useAuth } from './composables/useAuth';
|
|
4
|
+
import MasterPage from './components/MasterPage.vue';
|
|
5
|
+
import AppHeader from './components/AppHeader.vue';
|
|
6
|
+
import AppFooter from './components/AppFooter.vue';
|
|
7
|
+
import AppMenu from './components/AppMenu.vue';
|
|
8
|
+
export { MasterPage, AppHeader, AppFooter, AppMenu };
|
|
9
|
+
export { useAuth };
|
|
10
|
+
export type { MasterPageConfig, UserProfile, MenuItemConfig } from './models/types';
|
|
11
|
+
export type { OidcConfig } from './models/types';
|
|
12
|
+
declare const _default: {
|
|
13
|
+
install(app: App, config: MasterPageConfig): void;
|
|
14
|
+
};
|
|
15
|
+
export default _default;
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import { ref as A, readonly as I, defineComponent as x, openBlock as r, createElementBlock as i, createElementVNode as t, unref as p, createCommentVNode as j, toDisplayString as $, createTextVNode as K, normalizeClass as L, Fragment as P, createStaticVNode as W, renderList as O, onUnmounted as q, createVNode as F, renderSlot as J } from "vue";
|
|
2
|
+
import { UserManager as Q } from "oidc-client-ts";
|
|
3
|
+
const M = A(!1), T = A(null), E = A([]), V = A(!0);
|
|
4
|
+
let k, b, y = null;
|
|
5
|
+
function R() {
|
|
6
|
+
function g(e) {
|
|
7
|
+
k = e;
|
|
8
|
+
const o = {
|
|
9
|
+
authority: e.oidc.authority,
|
|
10
|
+
client_id: e.oidc.clientId,
|
|
11
|
+
client_secret: e.oidc.clientSecret,
|
|
12
|
+
redirect_uri: e.oidc.redirectUri ?? `${window.location.origin}?op=2`,
|
|
13
|
+
response_type: e.oidc.responseType ?? "code",
|
|
14
|
+
scope: e.oidc.scope ?? "openid profile email roles offline_access",
|
|
15
|
+
post_logout_redirect_uri: e.oidc.postLogoutRedirectUri ?? `${window.location.origin}?op=1`
|
|
16
|
+
};
|
|
17
|
+
b = new Q(o), a(), C();
|
|
18
|
+
}
|
|
19
|
+
function l() {
|
|
20
|
+
return k;
|
|
21
|
+
}
|
|
22
|
+
function n() {
|
|
23
|
+
b.signinRedirect({ prompt: "login" });
|
|
24
|
+
}
|
|
25
|
+
function f() {
|
|
26
|
+
const e = localStorage.getItem("access_token") ?? "", o = encodeURIComponent(
|
|
27
|
+
k.oidc.postLogoutRedirectUri ?? `${window.location.origin}?op=1`
|
|
28
|
+
);
|
|
29
|
+
window.location.href = `${k.oidc.authority}/connect/logout?id_token_hint=${e}&post_logout_redirect_uri=${o}`;
|
|
30
|
+
}
|
|
31
|
+
function u() {
|
|
32
|
+
window.location.href = `${k.oidc.authority}/Identity/Account/Manage?salir=1`;
|
|
33
|
+
}
|
|
34
|
+
async function h() {
|
|
35
|
+
const e = await b.getUser();
|
|
36
|
+
return (e == null ? void 0 : e.access_token) ?? null;
|
|
37
|
+
}
|
|
38
|
+
function a() {
|
|
39
|
+
const e = new URLSearchParams(window.location.search).get("op");
|
|
40
|
+
e === "2" && b.signinRedirectCallback().then(() => {
|
|
41
|
+
window.location.href = "/";
|
|
42
|
+
}).catch((o) => console.error("[MasterPage] signin callback error:", o)), e === "1" && b.signoutRedirectCallback().then(() => {
|
|
43
|
+
b.removeUser(), window.location.href = "/";
|
|
44
|
+
}).catch((o) => console.error("[MasterPage] signout callback error:", o));
|
|
45
|
+
}
|
|
46
|
+
async function C() {
|
|
47
|
+
try {
|
|
48
|
+
const e = await b.getUser();
|
|
49
|
+
e && !e.expired ? (m(e), k.enableFetchInterceptor !== !1 && s(), await v(e)) : (M.value = !1, T.value = null);
|
|
50
|
+
} catch (e) {
|
|
51
|
+
console.error("[MasterPage] session check error:", e), M.value = !1;
|
|
52
|
+
} finally {
|
|
53
|
+
V.value = !1;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function m(e) {
|
|
57
|
+
const o = e.profile;
|
|
58
|
+
T.value = {
|
|
59
|
+
firstName: o.UserFirstName ?? "",
|
|
60
|
+
middleName: o.UserMiddleName ?? "",
|
|
61
|
+
lastName: o.UserLastName ?? "",
|
|
62
|
+
secondLastName: o.UserSecondLastName ?? "",
|
|
63
|
+
enterpriseName: o.EnterpriseName ?? "",
|
|
64
|
+
displayName: [o.UserFirstName, o.UserMiddleName, o.UserLastName, o.UserSecondLastName].filter(Boolean).join(" ").trim(),
|
|
65
|
+
email: o.email ?? "",
|
|
66
|
+
accessToken: e.access_token,
|
|
67
|
+
rawClaims: o
|
|
68
|
+
}, localStorage.setItem("access_token", e.access_token), M.value = !0;
|
|
69
|
+
}
|
|
70
|
+
async function v(e) {
|
|
71
|
+
var o;
|
|
72
|
+
try {
|
|
73
|
+
const c = await fetch(`${k.oidc.authority}/connect/userinfo`, {
|
|
74
|
+
headers: { Authorization: `Bearer ${e.access_token}` }
|
|
75
|
+
});
|
|
76
|
+
if (!c.ok) return;
|
|
77
|
+
const w = await c.json();
|
|
78
|
+
(o = w == null ? void 0 : w.usrAuthorizations) != null && o.aplicaciones && (E.value = w.usrAuthorizations.aplicaciones);
|
|
79
|
+
} catch (c) {
|
|
80
|
+
console.error("[MasterPage] Failed to fetch authorizations:", c);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function s() {
|
|
84
|
+
if (y) return;
|
|
85
|
+
y = window.fetch.bind(window);
|
|
86
|
+
const e = k.oidc.authority;
|
|
87
|
+
window.fetch = async (o, c = {}) => {
|
|
88
|
+
if ((typeof o == "string" ? o : o.url).startsWith(e)) return y(o, c);
|
|
89
|
+
let _ = await b.getUser();
|
|
90
|
+
_ && !_.expired && (c.headers = { ...c.headers, Authorization: `Bearer ${_.access_token}` });
|
|
91
|
+
let d = await y(o, c);
|
|
92
|
+
if (d.status === 401 && _)
|
|
93
|
+
try {
|
|
94
|
+
const N = await b.signinSilent();
|
|
95
|
+
N && (m(N), c.headers = { ...c.headers, Authorization: `Bearer ${N.access_token}` }, d = await y(o, c));
|
|
96
|
+
} catch {
|
|
97
|
+
await b.signoutRedirect();
|
|
98
|
+
}
|
|
99
|
+
return d;
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function U() {
|
|
103
|
+
y && (window.fetch = y, y = null);
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
isAuthenticated: I(M),
|
|
107
|
+
userProfile: I(T),
|
|
108
|
+
menuItems: I(E),
|
|
109
|
+
isLoading: I(V),
|
|
110
|
+
configure: g,
|
|
111
|
+
getConfig: l,
|
|
112
|
+
login: n,
|
|
113
|
+
logout: f,
|
|
114
|
+
openAccountSettings: u,
|
|
115
|
+
getAccessToken: h,
|
|
116
|
+
destroyFetchInterceptor: U
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
const X = { class: "navbar-custom" }, Y = { class: "container-fluid" }, Z = {
|
|
120
|
+
class: "navbar-brand",
|
|
121
|
+
href: "#"
|
|
122
|
+
}, ee = ["src"], oe = { class: "brand-text" }, te = { class: "navbar-right" }, ne = {
|
|
123
|
+
key: 0,
|
|
124
|
+
class: "nav-item"
|
|
125
|
+
}, se = { class: "user-label" }, ae = /* @__PURE__ */ x({
|
|
126
|
+
__name: "AppHeader",
|
|
127
|
+
emits: ["menu-toggle"],
|
|
128
|
+
setup(g, { emit: l }) {
|
|
129
|
+
var w;
|
|
130
|
+
const n = l, { isAuthenticated: f, userProfile: u, login: h, logout: a, openAccountSettings: C, getConfig: m } = R(), v = A(!1), s = m(), U = (s == null ? void 0 : s.appTitle) ?? "SISPRO - Aplicativos Misionales", e = ((w = s == null ? void 0 : s.oidc) == null ? void 0 : w.authority) ?? "";
|
|
131
|
+
function o(_) {
|
|
132
|
+
_.stopPropagation(), v.value = !v.value;
|
|
133
|
+
}
|
|
134
|
+
function c() {
|
|
135
|
+
var d;
|
|
136
|
+
const _ = (d = m()) == null ? void 0 : d.registerUrl;
|
|
137
|
+
_ && (window.location.href = _);
|
|
138
|
+
}
|
|
139
|
+
return (_, d) => {
|
|
140
|
+
var N, z;
|
|
141
|
+
return r(), i("nav", X, [
|
|
142
|
+
t("div", Y, [
|
|
143
|
+
p(f) ? (r(), i("button", {
|
|
144
|
+
key: 0,
|
|
145
|
+
class: "menu-toggle",
|
|
146
|
+
onClick: d[0] || (d[0] = (S) => n("menu-toggle")),
|
|
147
|
+
"aria-label": "Toggle menu"
|
|
148
|
+
}, " ☰ ")) : j("", !0),
|
|
149
|
+
t("a", Z, [
|
|
150
|
+
t("img", {
|
|
151
|
+
src: `${p(e)}/img/logo.svg`,
|
|
152
|
+
alt: "Logo gov.co"
|
|
153
|
+
}, null, 8, ee),
|
|
154
|
+
t("span", oe, $(p(U)), 1)
|
|
155
|
+
]),
|
|
156
|
+
t("div", te, [
|
|
157
|
+
p(f) ? (r(), i("div", ne, [
|
|
158
|
+
t("a", {
|
|
159
|
+
class: "dropdown-user",
|
|
160
|
+
role: "button",
|
|
161
|
+
onClick: o
|
|
162
|
+
}, [
|
|
163
|
+
t("div", se, [
|
|
164
|
+
K($((N = p(u)) == null ? void 0 : N.displayName) + " ", 1),
|
|
165
|
+
t("span", null, $((z = p(u)) == null ? void 0 : z.enterpriseName), 1)
|
|
166
|
+
]),
|
|
167
|
+
d[4] || (d[4] = t("button", { class: "user-icon-btn" }, [
|
|
168
|
+
t("svg", {
|
|
169
|
+
width: "24",
|
|
170
|
+
height: "24",
|
|
171
|
+
viewBox: "0 0 24 24",
|
|
172
|
+
fill: "none",
|
|
173
|
+
stroke: "currentColor",
|
|
174
|
+
"stroke-width": "2",
|
|
175
|
+
"stroke-linecap": "round",
|
|
176
|
+
"stroke-linejoin": "round"
|
|
177
|
+
}, [
|
|
178
|
+
t("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }),
|
|
179
|
+
t("circle", {
|
|
180
|
+
cx: "12",
|
|
181
|
+
cy: "7",
|
|
182
|
+
r: "4"
|
|
183
|
+
})
|
|
184
|
+
])
|
|
185
|
+
], -1))
|
|
186
|
+
]),
|
|
187
|
+
t("ul", {
|
|
188
|
+
class: L(["dropdown-menu", { open: v.value }])
|
|
189
|
+
}, [
|
|
190
|
+
t("li", null, [
|
|
191
|
+
t("a", {
|
|
192
|
+
onClick: d[1] || (d[1] = //@ts-ignore
|
|
193
|
+
(...S) => p(C) && p(C)(...S))
|
|
194
|
+
}, "Configuración")
|
|
195
|
+
]),
|
|
196
|
+
t("li", null, [
|
|
197
|
+
t("a", {
|
|
198
|
+
onClick: d[2] || (d[2] = //@ts-ignore
|
|
199
|
+
(...S) => p(a) && p(a)(...S))
|
|
200
|
+
}, "Cerrar sesión")
|
|
201
|
+
])
|
|
202
|
+
], 2)
|
|
203
|
+
])) : (r(), i(P, { key: 1 }, [
|
|
204
|
+
t("button", {
|
|
205
|
+
class: "btn-login",
|
|
206
|
+
onClick: d[3] || (d[3] = //@ts-ignore
|
|
207
|
+
(...S) => p(h) && p(h)(...S))
|
|
208
|
+
}, "Ingresar"),
|
|
209
|
+
t("button", {
|
|
210
|
+
class: "btn-register",
|
|
211
|
+
onClick: c
|
|
212
|
+
}, "Registrarse")
|
|
213
|
+
], 64))
|
|
214
|
+
])
|
|
215
|
+
])
|
|
216
|
+
]);
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
}), B = (g, l) => {
|
|
220
|
+
const n = g.__vccOpts || g;
|
|
221
|
+
for (const [f, u] of l)
|
|
222
|
+
n[f] = u;
|
|
223
|
+
return n;
|
|
224
|
+
}, D = /* @__PURE__ */ B(ae, [["__scopeId", "data-v-69067b97"]]), re = { class: "shell-footer" }, ie = { class: "container" }, ce = { class: "row" }, le = { class: "col logos-col" }, ue = ["src"], de = ["src"], fe = /* @__PURE__ */ x({
|
|
225
|
+
__name: "AppFooter",
|
|
226
|
+
setup(g) {
|
|
227
|
+
var f, u;
|
|
228
|
+
const { getConfig: l } = R(), n = ((u = (f = l()) == null ? void 0 : f.oidc) == null ? void 0 : u.authority) ?? "";
|
|
229
|
+
return (h, a) => (r(), i("footer", re, [
|
|
230
|
+
t("div", ie, [
|
|
231
|
+
t("div", ce, [
|
|
232
|
+
t("div", le, [
|
|
233
|
+
t("img", {
|
|
234
|
+
src: `${p(n)}/img/logo.svg`,
|
|
235
|
+
alt: "GOV.CO",
|
|
236
|
+
class: "footer-logo"
|
|
237
|
+
}, null, 8, ue),
|
|
238
|
+
t("img", {
|
|
239
|
+
src: `${p(n)}/img/colombia.png`,
|
|
240
|
+
alt: "Colombia Potencia de la Vida",
|
|
241
|
+
class: "footer-logo"
|
|
242
|
+
}, null, 8, de)
|
|
243
|
+
]),
|
|
244
|
+
a[0] || (a[0] = W('<div class="col border-start" data-v-93fe5bbf><strong data-v-93fe5bbf>SISPRO</strong><p data-v-93fe5bbf> Dirección:<br data-v-93fe5bbf> Carrera 13 # 32–76 (piso 1)<br data-v-93fe5bbf> Cundinamarca, Bogotá D.C.<br data-v-93fe5bbf> Código Postal: 110311 </p><p data-v-93fe5bbf><a href="#" class="footer-link" data-v-93fe5bbf>Horario de atención:</a><br data-v-93fe5bbf> Lunes a viernes 8:00 a.m. a 4:00 p.m. </p></div><div class="col border-start" data-v-93fe5bbf><strong data-v-93fe5bbf>Contacto</strong><p data-v-93fe5bbf> Teléfono conmutador:<br data-v-93fe5bbf> En Bogotá: 601 330 5043 Opción 2<br data-v-93fe5bbf> Resto del país: 018000960020 Opción 2 </p><p data-v-93fe5bbf> Correo de notificaciones judiciales:<br data-v-93fe5bbf><a href="mailto:notificacionesjudiciales@minsalud.gov.co" class="footer-link" data-v-93fe5bbf> notificacionesjudiciales@minsalud.gov.co </a></p><p data-v-93fe5bbf><a href="https://www.minsalud.gov.co/Documents/Ministerio/Terminos%20y%20Condiciones%20de%20uso%20del%20portal%20web_Octubre%202012x.pdf" target="_blank" class="footer-link" data-v-93fe5bbf> Términos y condiciones </a></p></div>', 2))
|
|
245
|
+
])
|
|
246
|
+
])
|
|
247
|
+
]));
|
|
248
|
+
}
|
|
249
|
+
}), H = /* @__PURE__ */ B(fe, [["__scopeId", "data-v-93fe5bbf"]]), pe = { class: "menu-list" }, ge = ["onClick"], he = ["href"], _e = {
|
|
250
|
+
key: 2,
|
|
251
|
+
class: "submenu"
|
|
252
|
+
}, be = ["onClick"], me = ["href"], ve = {
|
|
253
|
+
key: 2,
|
|
254
|
+
class: "submenu"
|
|
255
|
+
}, we = ["href"], ke = /* @__PURE__ */ x({
|
|
256
|
+
__name: "AppMenu",
|
|
257
|
+
props: {
|
|
258
|
+
isOpen: { type: Boolean }
|
|
259
|
+
},
|
|
260
|
+
setup(g) {
|
|
261
|
+
const { menuItems: l } = R(), n = A(/* @__PURE__ */ new Set());
|
|
262
|
+
function f(u) {
|
|
263
|
+
n.value.has(u) ? n.value.delete(u) : n.value.add(u), n.value = new Set(n.value);
|
|
264
|
+
}
|
|
265
|
+
return (u, h) => (r(), i("aside", {
|
|
266
|
+
class: L(["sidebar-menu", { show: g.isOpen }])
|
|
267
|
+
}, [
|
|
268
|
+
t("ul", pe, [
|
|
269
|
+
(r(!0), i(P, null, O(p(l), (a) => {
|
|
270
|
+
var C, m, v;
|
|
271
|
+
return r(), i("li", {
|
|
272
|
+
key: a.nombre,
|
|
273
|
+
class: L({ "has-submenu": (C = a.hijos) == null ? void 0 : C.length, open: n.value.has(a) })
|
|
274
|
+
}, [
|
|
275
|
+
(m = a.hijos) != null && m.length ? (r(), i("span", {
|
|
276
|
+
key: 0,
|
|
277
|
+
class: "has-children",
|
|
278
|
+
onClick: (s) => f(a)
|
|
279
|
+
}, $(a.nombre), 9, ge)) : (r(), i("a", {
|
|
280
|
+
key: 1,
|
|
281
|
+
href: a.url || "#"
|
|
282
|
+
}, $(a.nombre), 9, he)),
|
|
283
|
+
(v = a.hijos) != null && v.length && n.value.has(a) ? (r(), i("ul", _e, [
|
|
284
|
+
(r(!0), i(P, null, O(a.hijos, (s) => {
|
|
285
|
+
var U, e, o;
|
|
286
|
+
return r(), i("li", {
|
|
287
|
+
key: s.nombre,
|
|
288
|
+
class: L({ "has-submenu": (U = s.hijos) == null ? void 0 : U.length, open: n.value.has(s) })
|
|
289
|
+
}, [
|
|
290
|
+
(e = s.hijos) != null && e.length ? (r(), i("span", {
|
|
291
|
+
key: 0,
|
|
292
|
+
class: "has-children",
|
|
293
|
+
onClick: (c) => f(s)
|
|
294
|
+
}, $(s.nombre), 9, be)) : (r(), i("a", {
|
|
295
|
+
key: 1,
|
|
296
|
+
href: s.url || "#"
|
|
297
|
+
}, $(s.nombre), 9, me)),
|
|
298
|
+
(o = s.hijos) != null && o.length && n.value.has(s) ? (r(), i("ul", ve, [
|
|
299
|
+
(r(!0), i(P, null, O(s.hijos, (c) => (r(), i("li", {
|
|
300
|
+
key: c.nombre
|
|
301
|
+
}, [
|
|
302
|
+
t("a", {
|
|
303
|
+
href: c.url || "#"
|
|
304
|
+
}, $(c.nombre), 9, we)
|
|
305
|
+
]))), 128))
|
|
306
|
+
])) : j("", !0)
|
|
307
|
+
], 2);
|
|
308
|
+
}), 128))
|
|
309
|
+
])) : j("", !0)
|
|
310
|
+
], 2);
|
|
311
|
+
}), 128))
|
|
312
|
+
])
|
|
313
|
+
], 2));
|
|
314
|
+
}
|
|
315
|
+
}), G = /* @__PURE__ */ B(ke, [["__scopeId", "data-v-1619503d"]]), ye = { class: "master-page-layout" }, $e = { class: "shell-main" }, Ce = /* @__PURE__ */ x({
|
|
316
|
+
__name: "MasterPage",
|
|
317
|
+
setup(g) {
|
|
318
|
+
const l = A(!1);
|
|
319
|
+
function n() {
|
|
320
|
+
l.value = !l.value;
|
|
321
|
+
}
|
|
322
|
+
function f() {
|
|
323
|
+
l.value = !1;
|
|
324
|
+
}
|
|
325
|
+
function u(h) {
|
|
326
|
+
h.key === "Escape" && f();
|
|
327
|
+
}
|
|
328
|
+
return window.addEventListener("keydown", u), q(() => window.removeEventListener("keydown", u)), (h, a) => (r(), i("div", ye, [
|
|
329
|
+
F(D, { onMenuToggle: n }),
|
|
330
|
+
F(G, { "is-open": l.value }, null, 8, ["is-open"]),
|
|
331
|
+
l.value ? (r(), i("div", {
|
|
332
|
+
key: 0,
|
|
333
|
+
class: "sidebar-backdrop",
|
|
334
|
+
onClick: f
|
|
335
|
+
})) : j("", !0),
|
|
336
|
+
t("main", $e, [
|
|
337
|
+
J(h.$slots, "default", {}, void 0, !0)
|
|
338
|
+
]),
|
|
339
|
+
F(H)
|
|
340
|
+
]));
|
|
341
|
+
}
|
|
342
|
+
}), Ae = /* @__PURE__ */ B(Ce, [["__scopeId", "data-v-ad151b79"]]), Se = {
|
|
343
|
+
install(g, l) {
|
|
344
|
+
const { configure: n } = R();
|
|
345
|
+
n(l), g.component("MasterPage", Ae), g.component("AppHeader", D), g.component("AppFooter", H), g.component("AppMenu", G);
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
export {
|
|
349
|
+
H as AppFooter,
|
|
350
|
+
D as AppHeader,
|
|
351
|
+
G as AppMenu,
|
|
352
|
+
Ae as MasterPage,
|
|
353
|
+
Se as default,
|
|
354
|
+
R as useAuth
|
|
355
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(m,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue"),require("oidc-client-ts")):typeof define=="function"&&define.amd?define(["exports","vue","oidc-client-ts"],e):(m=typeof globalThis<"u"?globalThis:m||self,e(m.MasterPageVue={},m.Vue,m.OidcClientTs))})(this,function(m,e,F){"use strict";const V=e.ref(!1),S=e.ref(null),I=e.ref([]),P=e.ref(!0);let _,p,u=null;function C(){function f(o){_=o;const t={authority:o.oidc.authority,client_id:o.oidc.clientId,client_secret:o.oidc.clientSecret,redirect_uri:o.oidc.redirectUri??`${window.location.origin}?op=2`,response_type:o.oidc.responseType??"code",scope:o.oidc.scope??"openid profile email roles offline_access",post_logout_redirect_uri:o.oidc.postLogoutRedirectUri??`${window.location.origin}?op=1`};p=new F.UserManager(t),s(),y()}function c(){return _}function n(){p.signinRedirect({prompt:"login"})}function d(){const o=localStorage.getItem("access_token")??"",t=encodeURIComponent(_.oidc.postLogoutRedirectUri??`${window.location.origin}?op=1`);window.location.href=`${_.oidc.authority}/connect/logout?id_token_hint=${o}&post_logout_redirect_uri=${t}`}function i(){window.location.href=`${_.oidc.authority}/Identity/Account/Manage?salir=1`}async function g(){const o=await p.getUser();return(o==null?void 0:o.access_token)??null}function s(){const o=new URLSearchParams(window.location.search).get("op");o==="2"&&p.signinRedirectCallback().then(()=>{window.location.href="/"}).catch(t=>console.error("[MasterPage] signin callback error:",t)),o==="1"&&p.signoutRedirectCallback().then(()=>{p.removeUser(),window.location.href="/"}).catch(t=>console.error("[MasterPage] signout callback error:",t))}async function y(){try{const o=await p.getUser();o&&!o.expired?(b(o),_.enableFetchInterceptor!==!1&&a(),await k(o)):(V.value=!1,S.value=null)}catch(o){console.error("[MasterPage] session check error:",o),V.value=!1}finally{P.value=!1}}function b(o){const t=o.profile;S.value={firstName:t.UserFirstName??"",middleName:t.UserMiddleName??"",lastName:t.UserLastName??"",secondLastName:t.UserSecondLastName??"",enterpriseName:t.EnterpriseName??"",displayName:[t.UserFirstName,t.UserMiddleName,t.UserLastName,t.UserSecondLastName].filter(Boolean).join(" ").trim(),email:t.email??"",accessToken:o.access_token,rawClaims:t},localStorage.setItem("access_token",o.access_token),V.value=!0}async function k(o){var t;try{const r=await fetch(`${_.oidc.authority}/connect/userinfo`,{headers:{Authorization:`Bearer ${o.access_token}`}});if(!r.ok)return;const w=await r.json();(t=w==null?void 0:w.usrAuthorizations)!=null&&t.aplicaciones&&(I.value=w.usrAuthorizations.aplicaciones)}catch(r){console.error("[MasterPage] Failed to fetch authorizations:",r)}}function a(){if(u)return;u=window.fetch.bind(window);const o=_.oidc.authority;window.fetch=async(t,r={})=>{if((typeof t=="string"?t:t.url).startsWith(o))return u(t,r);let h=await p.getUser();h&&!h.expired&&(r.headers={...r.headers,Authorization:`Bearer ${h.access_token}`});let l=await u(t,r);if(l.status===401&&h)try{const E=await p.signinSilent();E&&(b(E),r.headers={...r.headers,Authorization:`Bearer ${E.access_token}`},l=await u(t,r))}catch{await p.signoutRedirect()}return l}}function N(){u&&(window.fetch=u,u=null)}return{isAuthenticated:e.readonly(V),userProfile:e.readonly(S),menuItems:e.readonly(I),isLoading:e.readonly(P),configure:f,getConfig:c,login:n,logout:d,openAccountSettings:i,getAccessToken:g,destroyFetchInterceptor:N}}const T={class:"navbar-custom"},O={class:"container-fluid"},R={class:"navbar-brand",href:"#"},D=["src"],z={class:"brand-text"},x={class:"navbar-right"},H={key:0,class:"nav-item"},q={class:"user-label"},G=e.defineComponent({__name:"AppHeader",emits:["menu-toggle"],setup(f,{emit:c}){var w;const n=c,{isAuthenticated:d,userProfile:i,login:g,logout:s,openAccountSettings:y,getConfig:b}=C(),k=e.ref(!1),a=b(),N=(a==null?void 0:a.appTitle)??"SISPRO - Aplicativos Misionales",o=((w=a==null?void 0:a.oidc)==null?void 0:w.authority)??"";function t(h){h.stopPropagation(),k.value=!k.value}function r(){var l;const h=(l=b())==null?void 0:l.registerUrl;h&&(window.location.href=h)}return(h,l)=>{var E,j;return e.openBlock(),e.createElementBlock("nav",T,[e.createElementVNode("div",O,[e.unref(d)?(e.openBlock(),e.createElementBlock("button",{key:0,class:"menu-toggle",onClick:l[0]||(l[0]=B=>n("menu-toggle")),"aria-label":"Toggle menu"}," ☰ ")):e.createCommentVNode("",!0),e.createElementVNode("a",R,[e.createElementVNode("img",{src:`${e.unref(o)}/img/logo.svg`,alt:"Logo gov.co"},null,8,D),e.createElementVNode("span",z,e.toDisplayString(e.unref(N)),1)]),e.createElementVNode("div",x,[e.unref(d)?(e.openBlock(),e.createElementBlock("div",H,[e.createElementVNode("a",{class:"dropdown-user",role:"button",onClick:t},[e.createElementVNode("div",q,[e.createTextVNode(e.toDisplayString((E=e.unref(i))==null?void 0:E.displayName)+" ",1),e.createElementVNode("span",null,e.toDisplayString((j=e.unref(i))==null?void 0:j.enterpriseName),1)]),l[4]||(l[4]=e.createElementVNode("button",{class:"user-icon-btn"},[e.createElementVNode("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[e.createElementVNode("path",{d:"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"}),e.createElementVNode("circle",{cx:"12",cy:"7",r:"4"})])],-1))]),e.createElementVNode("ul",{class:e.normalizeClass(["dropdown-menu",{open:k.value}])},[e.createElementVNode("li",null,[e.createElementVNode("a",{onClick:l[1]||(l[1]=(...B)=>e.unref(y)&&e.unref(y)(...B))},"Configuración")]),e.createElementVNode("li",null,[e.createElementVNode("a",{onClick:l[2]||(l[2]=(...B)=>e.unref(s)&&e.unref(s)(...B))},"Cerrar sesión")])],2)])):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createElementVNode("button",{class:"btn-login",onClick:l[3]||(l[3]=(...B)=>e.unref(g)&&e.unref(g)(...B))},"Ingresar"),e.createElementVNode("button",{class:"btn-register",onClick:r},"Registrarse")],64))])])])}}}),$=(f,c)=>{const n=f.__vccOpts||f;for(const[d,i]of c)n[d]=i;return n},A=$(G,[["__scopeId","data-v-69067b97"]]),K={class:"shell-footer"},W={class:"container"},J={class:"row"},Q={class:"col logos-col"},X=["src"],Y=["src"],M=$(e.defineComponent({__name:"AppFooter",setup(f){var d,i;const{getConfig:c}=C(),n=((i=(d=c())==null?void 0:d.oidc)==null?void 0:i.authority)??"";return(g,s)=>(e.openBlock(),e.createElementBlock("footer",K,[e.createElementVNode("div",W,[e.createElementVNode("div",J,[e.createElementVNode("div",Q,[e.createElementVNode("img",{src:`${e.unref(n)}/img/logo.svg`,alt:"GOV.CO",class:"footer-logo"},null,8,X),e.createElementVNode("img",{src:`${e.unref(n)}/img/colombia.png`,alt:"Colombia Potencia de la Vida",class:"footer-logo"},null,8,Y)]),s[0]||(s[0]=e.createStaticVNode('<div class="col border-start" data-v-93fe5bbf><strong data-v-93fe5bbf>SISPRO</strong><p data-v-93fe5bbf> Dirección:<br data-v-93fe5bbf> Carrera 13 # 32–76 (piso 1)<br data-v-93fe5bbf> Cundinamarca, Bogotá D.C.<br data-v-93fe5bbf> Código Postal: 110311 </p><p data-v-93fe5bbf><a href="#" class="footer-link" data-v-93fe5bbf>Horario de atención:</a><br data-v-93fe5bbf> Lunes a viernes 8:00 a.m. a 4:00 p.m. </p></div><div class="col border-start" data-v-93fe5bbf><strong data-v-93fe5bbf>Contacto</strong><p data-v-93fe5bbf> Teléfono conmutador:<br data-v-93fe5bbf> En Bogotá: 601 330 5043 Opción 2<br data-v-93fe5bbf> Resto del país: 018000960020 Opción 2 </p><p data-v-93fe5bbf> Correo de notificaciones judiciales:<br data-v-93fe5bbf><a href="mailto:notificacionesjudiciales@minsalud.gov.co" class="footer-link" data-v-93fe5bbf> notificacionesjudiciales@minsalud.gov.co </a></p><p data-v-93fe5bbf><a href="https://www.minsalud.gov.co/Documents/Ministerio/Terminos%20y%20Condiciones%20de%20uso%20del%20portal%20web_Octubre%202012x.pdf" target="_blank" class="footer-link" data-v-93fe5bbf> Términos y condiciones </a></p></div>',2))])])]))}}),[["__scopeId","data-v-93fe5bbf"]]),Z={class:"menu-list"},v=["onClick"],ee=["href"],oe={key:2,class:"submenu"},te=["onClick"],ne=["href"],ae={key:2,class:"submenu"},se=["href"],U=$(e.defineComponent({__name:"AppMenu",props:{isOpen:{type:Boolean}},setup(f){const{menuItems:c}=C(),n=e.ref(new Set);function d(i){n.value.has(i)?n.value.delete(i):n.value.add(i),n.value=new Set(n.value)}return(i,g)=>(e.openBlock(),e.createElementBlock("aside",{class:e.normalizeClass(["sidebar-menu",{show:f.isOpen}])},[e.createElementVNode("ul",Z,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(c),s=>{var y,b,k;return e.openBlock(),e.createElementBlock("li",{key:s.nombre,class:e.normalizeClass({"has-submenu":(y=s.hijos)==null?void 0:y.length,open:n.value.has(s)})},[(b=s.hijos)!=null&&b.length?(e.openBlock(),e.createElementBlock("span",{key:0,class:"has-children",onClick:a=>d(s)},e.toDisplayString(s.nombre),9,v)):(e.openBlock(),e.createElementBlock("a",{key:1,href:s.url||"#"},e.toDisplayString(s.nombre),9,ee)),(k=s.hijos)!=null&&k.length&&n.value.has(s)?(e.openBlock(),e.createElementBlock("ul",oe,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(s.hijos,a=>{var N,o,t;return e.openBlock(),e.createElementBlock("li",{key:a.nombre,class:e.normalizeClass({"has-submenu":(N=a.hijos)==null?void 0:N.length,open:n.value.has(a)})},[(o=a.hijos)!=null&&o.length?(e.openBlock(),e.createElementBlock("span",{key:0,class:"has-children",onClick:r=>d(a)},e.toDisplayString(a.nombre),9,te)):(e.openBlock(),e.createElementBlock("a",{key:1,href:a.url||"#"},e.toDisplayString(a.nombre),9,ne)),(t=a.hijos)!=null&&t.length&&n.value.has(a)?(e.openBlock(),e.createElementBlock("ul",ae,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(a.hijos,r=>(e.openBlock(),e.createElementBlock("li",{key:r.nombre},[e.createElementVNode("a",{href:r.url||"#"},e.toDisplayString(r.nombre),9,se)]))),128))])):e.createCommentVNode("",!0)],2)}),128))])):e.createCommentVNode("",!0)],2)}),128))])],2))}}),[["__scopeId","data-v-1619503d"]]),re={class:"master-page-layout"},ce={class:"shell-main"},L=$(e.defineComponent({__name:"MasterPage",setup(f){const c=e.ref(!1);function n(){c.value=!c.value}function d(){c.value=!1}function i(g){g.key==="Escape"&&d()}return window.addEventListener("keydown",i),e.onUnmounted(()=>window.removeEventListener("keydown",i)),(g,s)=>(e.openBlock(),e.createElementBlock("div",re,[e.createVNode(A,{onMenuToggle:n}),e.createVNode(U,{"is-open":c.value},null,8,["is-open"]),c.value?(e.openBlock(),e.createElementBlock("div",{key:0,class:"sidebar-backdrop",onClick:d})):e.createCommentVNode("",!0),e.createElementVNode("main",ce,[e.renderSlot(g.$slots,"default",{},void 0,!0)]),e.createVNode(M)]))}}),[["__scopeId","data-v-ad151b79"]]),ie={install(f,c){const{configure:n}=C();n(c),f.component("MasterPage",L),f.component("AppHeader",A),f.component("AppFooter",M),f.component("AppMenu",U)}};m.AppFooter=M,m.AppHeader=A,m.AppMenu=U,m.MasterPage=L,m.default=ie,m.useAuth=C,Object.defineProperties(m,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface OidcConfig {
|
|
2
|
+
authority: string;
|
|
3
|
+
clientId: string;
|
|
4
|
+
clientSecret?: string;
|
|
5
|
+
redirectUri?: string;
|
|
6
|
+
postLogoutRedirectUri?: string;
|
|
7
|
+
scope?: string;
|
|
8
|
+
responseType?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface MasterPageConfig {
|
|
11
|
+
oidc: OidcConfig;
|
|
12
|
+
appTitle?: string;
|
|
13
|
+
assetsBasePath?: string;
|
|
14
|
+
enableFetchInterceptor?: boolean;
|
|
15
|
+
registerUrl?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface UserProfile {
|
|
18
|
+
firstName: string;
|
|
19
|
+
middleName: string;
|
|
20
|
+
lastName: string;
|
|
21
|
+
secondLastName: string;
|
|
22
|
+
enterpriseName: string;
|
|
23
|
+
displayName: string;
|
|
24
|
+
email?: string;
|
|
25
|
+
accessToken: string;
|
|
26
|
+
rawClaims: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
export interface MenuItemConfig {
|
|
29
|
+
readonly nombre: string;
|
|
30
|
+
readonly url?: string;
|
|
31
|
+
readonly hijos?: readonly MenuItemConfig[];
|
|
32
|
+
}
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.navbar-custom[data-v-69067b97]{background-color:#36c;box-shadow:0 4px 10px #0003;position:fixed;width:100%;z-index:1001;height:60px}.container-fluid[data-v-69067b97]{display:flex;align-items:center;width:100%;padding:0 15px}.navbar-brand[data-v-69067b97]{color:#fff;display:flex;align-items:center;gap:10px;text-decoration:none}.navbar-brand img[data-v-69067b97]{height:36px;margin-top:1px}.brand-text[data-v-69067b97]{padding-top:5px}.navbar-right[data-v-69067b97]{display:flex;align-items:center;margin-left:auto}.nav-item[data-v-69067b97]{position:relative}.dropdown-user[data-v-69067b97]{display:flex;align-items:center;gap:.5rem;color:#fff;cursor:pointer;text-decoration:none}.user-label[data-v-69067b97]{text-align:right;font-weight:500;line-height:1.2;color:#fff}.user-label span[data-v-69067b97]{display:block;font-size:.875rem;color:#e0e0e0}.user-icon-btn[data-v-69067b97]{background:transparent;border:none;color:#fff;cursor:pointer;padding:0}.dropdown-menu[data-v-69067b97]{display:none;position:absolute;right:0;top:50px;min-width:200px;background:#fff;border:1px solid #ddd;box-shadow:0 2px 6px #0000001a;border-radius:10px;list-style:none;margin:0;padding:0;z-index:1002}.dropdown-menu.open[data-v-69067b97]{display:block}.dropdown-menu li a[data-v-69067b97]{display:block;padding:10px 15px;color:#333;cursor:pointer;text-decoration:none}.dropdown-menu li a[data-v-69067b97]:hover{background:#f5f5f5}.menu-toggle[data-v-69067b97]{font-size:30px;border:none;background:transparent;color:#fff;cursor:pointer;margin-right:15px;padding:0;line-height:1}.btn-login[data-v-69067b97],.btn-register[data-v-69067b97]{margin-left:10px;border-radius:20px;font-weight:500;border:1px solid white;padding:6px 16px;cursor:pointer}.btn-login[data-v-69067b97]{color:#fff;background:transparent}.btn-register[data-v-69067b97]{color:#36c;background:#fff}@media (max-width: 860px){.navbar-brand[data-v-69067b97]{display:none}}.shell-footer[data-v-93fe5bbf]{background-color:#36c;color:#fff;padding:1.5rem 0;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-size:1em;width:100%}.container[data-v-93fe5bbf]{max-width:1200px;margin:0 auto;padding:0 15px}.row[data-v-93fe5bbf]{display:flex;flex-wrap:wrap;align-items:flex-start}.col[data-v-93fe5bbf]{flex:1;padding:0 15px}.logos-col[data-v-93fe5bbf]{display:flex;align-items:center;justify-content:center;gap:16px}.footer-logo[data-v-93fe5bbf]{max-height:50px}.border-start[data-v-93fe5bbf]{border-left:1px solid rgba(255,255,255,.3)}.footer-link[data-v-93fe5bbf]{color:#fff;text-decoration:underline}strong[data-v-93fe5bbf]{display:block;margin-bottom:.5rem}p[data-v-93fe5bbf]{margin:.25rem 0;line-height:1.5}@media (max-width: 768px){.col[data-v-93fe5bbf]{flex:0 0 100%;margin-bottom:1rem}.border-start[data-v-93fe5bbf]{border-left:none}}.sidebar-menu[data-v-1619503d]{position:fixed;top:0;left:0;height:100vh;width:300px;background-color:#36c;padding-top:60px;transform:translate(-100%);transition:transform .3s ease;z-index:1000;overflow-y:auto}.sidebar-menu.show[data-v-1619503d]{transform:translate(0)}.menu-list[data-v-1619503d],.submenu[data-v-1619503d]{list-style:none;padding:0;margin:0}.submenu[data-v-1619503d]{padding-left:10px}li a[data-v-1619503d],li span[data-v-1619503d]{display:block;padding:10px;color:#fff;text-decoration:none;font-weight:500;cursor:pointer}li a[data-v-1619503d]:hover,li span[data-v-1619503d]:hover{background-color:#2952a3}.has-submenu>span.has-children[data-v-1619503d]:after{content:" ▼";font-size:.8em;float:right}.has-submenu.open>span.has-children[data-v-1619503d]:after{content:" ▲"}.master-page-layout[data-v-ad151b79]{display:flex;flex-direction:column;min-height:100vh;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.shell-main[data-v-ad151b79]{flex:1;padding-top:65px;min-height:calc(100vh - 260px)}.sidebar-backdrop[data-v-ad151b79]{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000059;z-index:999;cursor:pointer;transition:opacity .3s ease}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "master-page-vue",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Master page layout with OIDC auth for Vue 3",
|
|
5
|
+
"main": "dist/master-page-vue.umd.cjs",
|
|
6
|
+
"module": "dist/master-page-vue.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/master-page-vue.js",
|
|
11
|
+
"require": "./dist/master-page-vue.umd.cjs",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": ["dist"],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "vite build && vue-tsc --emitDeclarationOnly",
|
|
18
|
+
"dev": "vite"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"vue": "^3.0.0"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"oidc-client-ts": "^3.0.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@vitejs/plugin-vue": "^5.0.0",
|
|
28
|
+
"typescript": "^5.0.0",
|
|
29
|
+
"vite": "^5.0.0",
|
|
30
|
+
"vite-plugin-dts": "^3.0.0",
|
|
31
|
+
"vue": "^3.4.0",
|
|
32
|
+
"vue-tsc": "^2.0.0"
|
|
33
|
+
}
|
|
34
|
+
}
|