mirror of https://github.com/Requarks/wiki.git
36 changed files with 1116 additions and 958 deletions
Split View
Diff Options
-
5Makefile
-
101client/components/admin.vue
-
2client/components/admin/admin-auth.vue
-
75client/components/admin/admin-dashboard.vue
-
203client/components/admin/admin-groups-edit-permissions.vue
-
302client/components/admin/admin-groups-edit-rules.vue
-
147client/components/admin/admin-groups-edit-users.vue
-
306client/components/admin/admin-groups-edit.vue
-
58client/components/admin/admin-groups.vue
-
19client/components/admin/admin-system.vue
-
38client/components/admin/admin-users-create.vue
-
211client/components/common/criterias-item.vue
-
173client/components/common/criterias.vue
-
234client/components/common/nav-header.vue
-
16client/components/common/user-search.vue
-
1client/components/editor.vue
-
4client/graph/admin/groups/groups-mutation-update.gql
-
7client/graph/admin/groups/groups-query-single.gql
-
1client/graph/admin/system/system-query-info.gql
-
4client/static/svg/icon-apple-logo.svg
-
13client/static/svg/icon-delete-file.svg
-
4client/static/svg/icon-docker-logo.svg
-
4client/static/svg/icon-linux-logo.svg
-
4client/static/svg/icon-windows-logo.svg
-
26client/themes/default/components/page.vue
-
35dev/scripts/docker-clean-db.js
-
8package.json
-
1server/db/migrations/2.0.0.js
-
7server/graph/resolvers/group.js
-
7server/graph/resolvers/system.js
-
42server/graph/schemas/group.graphql
-
1server/graph/schemas/system.graphql
-
2server/jobs/purge-uploads.js
-
1server/master.js
-
10server/setup.js
-
2server/views/new.pug
@ -0,0 +1,203 @@ |
|||
<template lang="pug"> |
|||
v-card.wiki-form(flat) |
|||
v-card-text |
|||
v-text-field( |
|||
outline |
|||
background-color='grey lighten-3' |
|||
v-model='group.name' |
|||
label='Group Name' |
|||
counter='255' |
|||
prepend-icon='people' |
|||
) |
|||
v-alert.radius-7( |
|||
v-if='group.isSystem' |
|||
color='orange darken-2' |
|||
:class='$vuetify.dark ? "grey darken-4" : "orange lighten-5"' |
|||
outline |
|||
:value='true' |
|||
icon='lock_outline' |
|||
) This is a system group. Some permissions cannot be modified. |
|||
v-container.px-3.pb-3.pt-0(fluid, grid-list-md) |
|||
v-layout(row, wrap) |
|||
v-flex(xs12, md6, lg4, v-for='pmGroup in permissions') |
|||
v-card.md2(flat, :class='$vuetify.dark ? "grey darken-3-d5" : "white"') |
|||
v-subheader {{pmGroup.category}} |
|||
v-card-text.pt-0 |
|||
template(v-for='(pm, idx) in pmGroup.items') |
|||
v-checkbox.pt-0( |
|||
:key='pm.permission' |
|||
:label='pm.permission' |
|||
:hint='pm.hint' |
|||
persistent-hint |
|||
color='primary' |
|||
v-model='group.permissions' |
|||
:value='pm.permission' |
|||
:append-icon='pm.warning ? "warning" : null', |
|||
:disabled='(group.isSystem && pm.restrictedForSystem) || group.id === 1 || pm.disabled' |
|||
) |
|||
v-divider.mt-3(v-if='idx < pmGroup.items.length - 1') |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
props: { |
|||
value: { |
|||
type: Object |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
permissions: [ |
|||
{ |
|||
category: 'Content', |
|||
items: [ |
|||
{ |
|||
permission: 'read:pages', |
|||
hint: 'Can view pages, as specified in the Page Rules', |
|||
warning: false, |
|||
restrictedForSystem: false, |
|||
disabled: false |
|||
}, |
|||
{ |
|||
permission: 'write:pages', |
|||
hint: 'Can view and create new pages, as specified in the Page Rules', |
|||
warning: false, |
|||
restrictedForSystem: false, |
|||
disabled: false |
|||
}, |
|||
{ |
|||
permission: 'manage:pages', |
|||
hint: 'Can view, create, edit and move existing pages as specified in the Page Rules', |
|||
warning: false, |
|||
restrictedForSystem: false, |
|||
disabled: false |
|||
}, |
|||
{ |
|||
permission: 'delete:pages', |
|||
hint: 'Can delete existing pages, as specified in the Page Rules', |
|||
warning: false, |
|||
restrictedForSystem: false, |
|||
disabled: false |
|||
}, |
|||
{ |
|||
permission: 'read:assets', |
|||
hint: 'Can view / use assets (such as images and files), as specified in the Page Rules', |
|||
warning: false, |
|||
restrictedForSystem: false, |
|||
disabled: false |
|||
}, |
|||
{ |
|||
permission: 'write:assets', |
|||
hint: 'Can upload new assets (such as images and files), as specified in the Page Rules', |
|||
warning: false, |
|||
restrictedForSystem: false, |
|||
disabled: false |
|||
}, |
|||
{ |
|||
permission: 'manage:assets', |
|||
hint: 'Can edit and delete assets (such as images and files), as specified in the Page Rules', |
|||
warning: false, |
|||
restrictedForSystem: false, |
|||
disabled: false |
|||
}, |
|||
{ |
|||
permission: 'read:comments', |
|||
hint: 'Can view comments, as specified in the Page Rules', |
|||
warning: false, |
|||
restrictedForSystem: false, |
|||
disabled: false |
|||
}, |
|||
{ |
|||
permission: 'write:comments', |
|||
hint: 'Can post new comments, as specified in the Page Rules', |
|||
warning: false, |
|||
restrictedForSystem: false, |
|||
disabled: false |
|||
}, |
|||
{ |
|||
permission: 'manage:comments', |
|||
hint: 'Can edit and delete comments, as specified in the Page Rules', |
|||
warning: false, |
|||
restrictedForSystem: false, |
|||
disabled: false |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
category: 'Users', |
|||
items: [ |
|||
{ |
|||
permission: 'write:users', |
|||
hint: 'Can create or authorize new users, but not modify existing ones', |
|||
warning: false, |
|||
restrictedForSystem: true, |
|||
disabled: false |
|||
}, |
|||
{ |
|||
permission: 'manage:users', |
|||
hint: 'Can manage all users (but not users with administrative permissions)', |
|||
warning: false, |
|||
restrictedForSystem: true, |
|||
disabled: false |
|||
}, |
|||
{ |
|||
permission: 'write:groups', |
|||
hint: 'Can manage groups and assign CONTENT permissions / page rules', |
|||
warning: false, |
|||
restrictedForSystem: true, |
|||
disabled: false |
|||
}, |
|||
{ |
|||
permission: 'manage:groups', |
|||
hint: 'Can manage groups and assign ANY permissions (but not manage:system) / page rules', |
|||
warning: true, |
|||
restrictedForSystem: true, |
|||
disabled: false |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
category: 'Administration', |
|||
items: [ |
|||
{ |
|||
permission: 'manage:navigation', |
|||
hint: 'Can manage the site navigation', |
|||
warning: false, |
|||
restrictedForSystem: true, |
|||
disabled: false |
|||
}, |
|||
{ |
|||
permission: 'manage:theme', |
|||
hint: 'Can manage and modify themes', |
|||
warning: false, |
|||
restrictedForSystem: true, |
|||
disabled: false |
|||
}, |
|||
{ |
|||
permission: 'manage:api', |
|||
hint: 'Can generate and revoke API keys', |
|||
warning: true, |
|||
restrictedForSystem: true, |
|||
disabled: false |
|||
}, |
|||
{ |
|||
permission: 'manage:system', |
|||
hint: 'Can manage and access everything. Root administrator.', |
|||
warning: true, |
|||
restrictedForSystem: true, |
|||
disabled: true |
|||
|
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
}, |
|||
computed: { |
|||
group: { |
|||
get() { return this.value }, |
|||
set(val) { this.$set('input', val) } |
|||
} |
|||
} |
|||
} |
|||
</script> |
@ -0,0 +1,302 @@ |
|||
<template lang="pug"> |
|||
v-card.wiki-form |
|||
v-card-text(v-if='group.id === 1') |
|||
v-alert.radius-7( |
|||
:class='$vuetify.dark ? "grey darken-4" : "orange lighten-5"' |
|||
color='orange darken-2' |
|||
outline |
|||
:value='true' |
|||
icon='lock_outline' |
|||
) This group has access to everything. |
|||
template(v-else) |
|||
v-card-title(:class='$vuetify.dark ? `grey darken-3-d5` : `grey lighten-5`') |
|||
v-alert.radius-7( |
|||
:class='$vuetify.dark ? `grey darken-3-d3` : `white`' |
|||
:value='true' |
|||
color='grey' |
|||
outline |
|||
icon='info' |
|||
) You must enable global content permissions (under Permissions tab) for page rules to have any effect. |
|||
v-spacer |
|||
v-btn(depressed, color='primary', @click='addRule') |
|||
v-icon(left) add |
|||
| Add Rule |
|||
v-menu( |
|||
right |
|||
offset-y |
|||
nudge-left='115' |
|||
) |
|||
v-btn.is-icon(slot='activator', flat, outline, color='primary') |
|||
v-icon more_horiz |
|||
v-list(dense) |
|||
v-list-tile(@click='comingSoon') |
|||
v-list-tile-avatar |
|||
v-icon keyboard_capslock |
|||
v-list-tile-title Load Preset |
|||
v-divider |
|||
v-list-tile(@click='comingSoon') |
|||
v-list-tile-avatar |
|||
v-icon publish |
|||
v-list-tile-title Save As Preset |
|||
v-divider |
|||
v-list-tile(@click='comingSoon') |
|||
v-list-tile-avatar |
|||
v-icon cloud_upload |
|||
v-list-tile-title Import Rules |
|||
v-divider |
|||
v-list-tile(@click='comingSoon') |
|||
v-list-tile-avatar |
|||
v-icon cloud_download |
|||
v-list-tile-title Export Rules |
|||
v-card-text(:class='$vuetify.dark ? `grey darken-4-l5` : `white`') |
|||
.rules |
|||
.caption(v-if='group.pageRules.length === 0') |
|||
em(:class='$vuetify.dark ? `grey--text` : `blue-grey--text`') This group has no page rules yet. |
|||
.rule(v-for='rule of group.pageRules', :key='rule.id') |
|||
v-btn.ma-0.rule-deny-btn( |
|||
solo |
|||
:color='rule.deny ? "red" : "green"' |
|||
dark |
|||
@click='rule.deny = !rule.deny' |
|||
) |
|||
v-icon(v-if='rule.deny') block |
|||
v-icon(v-else) check_circle |
|||
//- Roles |
|||
v-select.ml-1( |
|||
solo |
|||
:items='roles' |
|||
v-model='rule.roles' |
|||
placeholder='Select Role(s)...' |
|||
hide-details |
|||
multiple |
|||
chips |
|||
deletable-chips |
|||
small-chips |
|||
style='flex: 0 1 440px;' |
|||
:menu-props='{ "maxHeight": 500 }' |
|||
clearable |
|||
dense |
|||
) |
|||
template(slot='selection', slot-scope='{ item, index }') |
|||
v-chip.white--text.ml-0(v-if='index <= 2', small, label, :color='rule.deny ? `red` : `green`').caption {{ item.value }} |
|||
v-chip.white--text.ml-0(v-if='index === 3', small, label, :color='rule.deny ? `red lighten-2` : `green lighten-2`').caption + {{ rule.roles.length - 3 }} more |
|||
template(slot='item', slot-scope='props') |
|||
v-list-tile-action(style='min-width: 30px;') |
|||
v-checkbox( |
|||
v-model='props.tile.props.value' |
|||
hide-details |
|||
color='primary' |
|||
) |
|||
v-icon.mr-2(:color='rule.deny ? `red` : `green`') {{props.item.icon}} |
|||
v-list-tile-content |
|||
v-list-tile-title.body-2 {{props.item.text}} |
|||
v-chip.mr-2.grey--text(label, small, :color='$vuetify.dark ? `grey darken-4` : `grey lighten-4`').caption {{props.item.value}} |
|||
|
|||
//- Match |
|||
v-select.ml-1.mr-1( |
|||
solo |
|||
:items='matches' |
|||
v-model='rule.match' |
|||
placeholder='Match...' |
|||
hide-details |
|||
style='flex: 0 1 250px;' |
|||
dense |
|||
) |
|||
template(slot='selection', slot-scope='{ item, index }') |
|||
.body-1 {{item.text}} |
|||
template(slot='item', slot-scope='data') |
|||
v-list-tile-avatar |
|||
v-avatar.white--text.radius-4(color='blue', size='30', tile) {{ data.item.icon }} |
|||
v-list-tile-content |
|||
v-list-tile-title(v-html='data.item.text') |
|||
//- Locales |
|||
v-select.mr-1( |
|||
:background-color='$vuetify.dark ? `grey darken-3-d5` : `blue-grey lighten-5`' |
|||
solo |
|||
:items='locales' |
|||
v-model='rule.locales' |
|||
placeholder='Any Locale' |
|||
multiple |
|||
hide-details |
|||
dense |
|||
:menu-props='{ "minWidth": 250 }' |
|||
style='flex: 0 1 150px;' |
|||
) |
|||
template(slot='selection', slot-scope='{ item, index }') |
|||
v-chip.white--text.ml-0(v-if='rule.locales.length === 1', small, label, :color='rule.deny ? `red` : `green`').caption {{ item.value.toUpperCase() }} |
|||
v-chip.white--text.ml-0(v-else-if='index === 0', small, label, :color='rule.deny ? `red` : `green`').caption {{ rule.locales.length }} locales |
|||
v-list-tile(slot='prepend-item', @click='rule.locales = []') |
|||
v-list-tile-action(style='min-width: 30px;') |
|||
v-checkbox( |
|||
:input-value='rule.locales.length === 0' |
|||
hide-details |
|||
color='primary' |
|||
readonly |
|||
) |
|||
v-icon.mr-2(:color='rule.deny ? `red` : `green`') public |
|||
v-list-tile-content |
|||
v-list-tile-title.body-2 Any Locale |
|||
v-divider(slot='prepend-item') |
|||
template(slot='item', slot-scope='props') |
|||
v-list-tile-action(style='min-width: 30px;') |
|||
v-checkbox( |
|||
v-model='props.tile.props.value' |
|||
hide-details |
|||
color='primary' |
|||
) |
|||
v-icon.mr-2(:color='rule.deny ? `red` : `green`') language |
|||
v-list-tile-content |
|||
v-list-tile-title.body-2 {{props.item.text}} |
|||
v-chip.mr-2.grey--text(label, small, :color='$vuetify.dark ? `grey darken-4` : `grey lighten-4`').caption {{props.item.value.toUpperCase()}} |
|||
|
|||
//- Path |
|||
v-text-field( |
|||
solo |
|||
v-model='rule.path' |
|||
label='Path' |
|||
:prefix='rule.match !== `END` ? `/` : null' |
|||
:placeholder='rule.match === `REGEX` ? `Regular Expression` : `Path`' |
|||
:suffix='rule.match === `REGEX` ? `/` : null' |
|||
hide-details |
|||
:color='$vuetify.dark ? `grey` : `blue-grey`' |
|||
) |
|||
|
|||
v-btn(icon, @click='removeRule(rule.id)') |
|||
v-icon(:color='$vuetify.dark ? `grey` : `blue-grey`') clear |
|||
</template> |
|||
|
|||
<script> |
|||
import _ from 'lodash' |
|||
import nanoid from 'nanoid/non-secure/generate' |
|||
|
|||
export default { |
|||
props: { |
|||
value: { |
|||
type: Object |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
roles: [ |
|||
{ text: 'Read Pages', value: 'READ', icon: 'insert_drive_file' }, |
|||
{ text: 'Create Pages', value: 'WRITE', icon: 'insert_drive_file' }, |
|||
{ text: 'Edit + Move Pages', value: 'MANAGE', icon: 'insert_drive_file' }, |
|||
{ text: 'Delete Pages', value: 'DELETE', icon: 'insert_drive_file' }, |
|||
{ text: 'Read / Use Assets', value: 'AS_READ', icon: 'camera' }, |
|||
{ text: 'Upload Assets', value: 'AS_WRITE', icon: 'camera' }, |
|||
{ text: 'Edit + Delete Assets', value: 'AS_MANAGE', icon: 'camera' }, |
|||
{ text: 'Read Comments', value: 'CM_READ', icon: 'insert_comment' }, |
|||
{ text: 'Create Comments', value: 'CM_WRITE', icon: 'insert_comment' }, |
|||
{ text: 'Edit + Delete Comments', value: 'CM_MANAGE', icon: 'insert_comment' } |
|||
], |
|||
matches: [ |
|||
{ text: 'Path Starts With...', value: 'START', icon: '/...' }, |
|||
{ text: 'Path is Exactly...', value: 'EXACT', icon: '=' }, |
|||
{ text: 'Path Ends With...', value: 'END', icon: '.../' }, |
|||
{ text: 'Path Matches Regex...', value: 'REGEX', icon: '$.*' } |
|||
], |
|||
locales: [ |
|||
{ text: 'English', value: 'en' }, |
|||
{ text: 'Français', value: 'fr' }, |
|||
] |
|||
} |
|||
}, |
|||
computed: { |
|||
group: { |
|||
get() { return this.value }, |
|||
set(val) { this.$set('input', val) } |
|||
} |
|||
}, |
|||
methods: { |
|||
addRule(group) { |
|||
this.group.pageRules.push({ |
|||
id: nanoid('1234567890abcdef', 10), |
|||
path: '', |
|||
roles: [], |
|||
match: 'START', |
|||
deny: false, |
|||
locales: [] |
|||
}) |
|||
}, |
|||
removeRule(rule) { |
|||
this.group.pageRules.splice(_.findIndex(this.group.pageRules, ['id', rule.id]), 1) |
|||
}, |
|||
comingSoon() { |
|||
this.$store.commit('showNotification', { |
|||
style: 'indigo', |
|||
message: `Coming soon...`, |
|||
icon: 'directions_boat' |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.rules { |
|||
background-color: mc('blue-grey', '50'); |
|||
border-radius: 4px; |
|||
padding: 1rem; |
|||
position: relative; |
|||
|
|||
@at-root .theme--dark & { |
|||
background-color: mc('grey', '800'); |
|||
} |
|||
} |
|||
|
|||
.rule { |
|||
display: flex; |
|||
background-color: mc('blue-grey', '100'); |
|||
border-radius: 4px; |
|||
padding: .5rem; |
|||
|
|||
&-enter-active, &-leave-active { |
|||
transition: all .5s ease; |
|||
} |
|||
&-enter, &-leave-to { |
|||
opacity: 0; |
|||
} |
|||
|
|||
@at-root .theme--dark & { |
|||
background-color: mc('grey', '700'); |
|||
} |
|||
|
|||
& + .rule { |
|||
margin-top: .5rem; |
|||
position: relative; |
|||
|
|||
&::before { |
|||
content: '+'; |
|||
position: absolute; |
|||
width: 2rem; |
|||
height: 2rem; |
|||
border-radius: 50%; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
font-weight: 600; |
|||
color: mc('blue-grey', '700'); |
|||
font-size: 1.25rem; |
|||
background-color: mc('blue-grey', '50'); |
|||
left: -2rem; |
|||
top: -1.3rem; |
|||
|
|||
@at-root .theme--dark & { |
|||
background-color: mc('grey', '800'); |
|||
color: mc('grey', '600'); |
|||
} |
|||
} |
|||
} |
|||
|
|||
.input-group + * { |
|||
margin-left: .5rem; |
|||
} |
|||
|
|||
&-deny-btn { |
|||
height: 48px; |
|||
border-radius: 2px 0 0 2px; |
|||
min-width: 0; |
|||
} |
|||
|
|||
} |
|||
</style> |
@ -0,0 +1,147 @@ |
|||
<template lang="pug"> |
|||
v-card.wiki-form |
|||
v-card-title(:class='$vuetify.dark ? `grey darken-3-d3` : `grey lighten-5`') |
|||
v-text-field( |
|||
outline |
|||
flat |
|||
prepend-inner-icon='search' |
|||
v-model='search' |
|||
label='Search Group Users...' |
|||
hide-details |
|||
) |
|||
v-spacer |
|||
v-btn(color='primary', depressed, @click='searchUserDialog = true', :disabled='group.id === 2') |
|||
v-icon(left) assignment_ind |
|||
| Assign User |
|||
v-data-table( |
|||
:items='group.users', |
|||
:headers='headers', |
|||
:search='search' |
|||
:pagination.sync='pagination', |
|||
:rows-per-page-items='[15]' |
|||
hide-actions |
|||
) |
|||
template(slot='items', slot-scope='props') |
|||
tr(:active='props.selected') |
|||
td.text-xs-right {{ props.item.id }} |
|||
td {{ props.item.name }} |
|||
td {{ props.item.email }} |
|||
td |
|||
v-menu(bottom, right, min-width='200') |
|||
v-btn(icon, slot='activator'): v-icon.grey--text.text--darken-1 more_horiz |
|||
v-list |
|||
v-list-tile(:to='`/users/` + props.item.id') |
|||
v-list-tile-action: v-icon(color='primary') person |
|||
v-list-tile-content |
|||
v-list-tile-title View User Profile |
|||
template(v-if='props.item.id !== 2') |
|||
v-divider |
|||
v-list-tile(@click='unassignUser(props.item.id)') |
|||
v-list-tile-action: v-icon(color='orange') highlight_off |
|||
v-list-tile-content |
|||
v-list-tile-title Unassign |
|||
template(slot='no-data') |
|||
v-alert.ma-3(icon='warning', :value='true', outline) No users to display. |
|||
.text-xs-center.py-2(v-if='group.users.length > 15') |
|||
v-pagination(v-model='pagination.page', :length='pages') |
|||
|
|||
user-search(v-model='searchUserDialog', @select='assignUser') |
|||
</template> |
|||
|
|||
<script> |
|||
import UserSearch from '../common/user-search.vue' |
|||
|
|||
import assignUserMutation from 'gql/admin/groups/groups-mutation-assign.gql' |
|||
import unassignUserMutation from 'gql/admin/groups/groups-mutation-unassign.gql' |
|||
|
|||
export default { |
|||
props: { |
|||
value: { |
|||
type: Object |
|||
} |
|||
}, |
|||
components: { |
|||
UserSearch |
|||
}, |
|||
data() { |
|||
return { |
|||
headers: [ |
|||
{ text: 'ID', value: 'id', width: 50, align: 'right' }, |
|||
{ text: 'Name', value: 'name' }, |
|||
{ text: 'Email', value: 'email' }, |
|||
{ text: '', value: 'actions', sortable: false, width: 50 } |
|||
], |
|||
searchUserDialog: false, |
|||
pagination: {}, |
|||
search: '' |
|||
} |
|||
}, |
|||
computed: { |
|||
group: { |
|||
get() { return this.value }, |
|||
set(val) { this.$set('input', val) } |
|||
}, |
|||
pages () { |
|||
if (this.pagination.rowsPerPage == null || this.pagination.totalItems == null) { |
|||
return 0 |
|||
} |
|||
|
|||
return Math.ceil(this.pagination.totalItems / this.pagination.rowsPerPage) |
|||
} |
|||
}, |
|||
methods: { |
|||
async assignUser(id) { |
|||
try { |
|||
await this.$apollo.mutate({ |
|||
mutation: assignUserMutation, |
|||
variables: { |
|||
groupId: this.group.id, |
|||
userId: id |
|||
}, |
|||
watchLoading (isLoading) { |
|||
this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-groups-assign') |
|||
} |
|||
}) |
|||
this.$store.commit('showNotification', { |
|||
style: 'success', |
|||
message: `User has been assigned to ${this.group.name}.`, |
|||
icon: 'assignment_ind' |
|||
}) |
|||
this.$emit('refresh') |
|||
} catch (err) { |
|||
this.$store.commit('showNotification', { |
|||
style: 'red', |
|||
message: err.message, |
|||
icon: 'warning' |
|||
}) |
|||
} |
|||
}, |
|||
async unassignUser(id) { |
|||
try { |
|||
await this.$apollo.mutate({ |
|||
mutation: unassignUserMutation, |
|||
variables: { |
|||
groupId: this.group.id, |
|||
userId: id |
|||
}, |
|||
watchLoading (isLoading) { |
|||
this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-groups-unassign') |
|||
} |
|||
}) |
|||
this.$store.commit('showNotification', { |
|||
style: 'success', |
|||
message: `User has been unassigned from ${this.group.name}.`, |
|||
icon: 'assignment_ind' |
|||
}) |
|||
this.$emit('refresh') |
|||
} catch (err) { |
|||
this.$store.commit('showNotification', { |
|||
style: 'red', |
|||
message: err.message, |
|||
icon: 'warning' |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
@ -1,211 +0,0 @@ |
|||
<template lang="pug"> |
|||
.criterias-item |
|||
//- Type |
|||
v-select( |
|||
solo |
|||
:items='filteredCriteriaTypes' |
|||
v-model='item.type' |
|||
placeholder='Rule Type' |
|||
ref='typeSelect' |
|||
hide-details |
|||
) |
|||
template(slot='item', slot-scope='data') |
|||
v-list-tile-avatar |
|||
v-avatar(:color='data.item.color', size='40', tile): v-icon(color='white') {{ data.item.icon }} |
|||
v-list-tile-content |
|||
v-list-tile-title(v-html='data.item.text') |
|||
v-list-tile-sub-title.caption(v-html='data.item.description') |
|||
|
|||
//- Operator |
|||
v-select( |
|||
solo |
|||
:items='filteredCriteriaOperators' |
|||
v-model='item.operator' |
|||
placeholder='Operator' |
|||
:disabled='!item.type' |
|||
:class='!item.type ? "blue-grey lighten-4" : ""' |
|||
hide-details |
|||
) |
|||
template(slot='item', slot-scope='data') |
|||
v-list-tile-avatar |
|||
v-avatar.white--text(color='blue', size='30', tile) {{ data.item.icon }} |
|||
v-list-tile-content |
|||
v-list-tile-title(v-html='data.item.text') |
|||
|
|||
//- Value |
|||
v-select( |
|||
v-if='item.type === "country"' |
|||
solo |
|||
:items='countries' |
|||
v-model='item.value' |
|||
placeholder='Countries...' |
|||
multiple |
|||
item-text='name' |
|||
item-value='code' |
|||
hide-details |
|||
) |
|||
v-text-field( |
|||
v-else-if='item.type === "path"' |
|||
solo |
|||
v-model='item.value' |
|||
label='Path (e.g. /section)' |
|||
hide-details |
|||
) |
|||
v-text-field( |
|||
v-else-if='item.type === "date"' |
|||
solo |
|||
@click.native.stop='dateActivator = true' |
|||
v-model='item.value' |
|||
label='YYYY-MM-DD' |
|||
readonly |
|||
hide-details |
|||
) |
|||
v-text-field( |
|||
v-else-if='item.type === "time"' |
|||
solo |
|||
@click.native.stop='timeActivator = true' |
|||
v-model='item.value' |
|||
label='HH:MM' |
|||
readonly |
|||
hide-details |
|||
) |
|||
v-select( |
|||
v-else-if='item.type === "group"' |
|||
solo |
|||
:items='groups' |
|||
v-model='item.value' |
|||
placeholder='Group...' |
|||
item-text='name' |
|||
item-value='id' |
|||
hide-details |
|||
) |
|||
v-text-field.blue-grey.lighten-4( |
|||
v-else |
|||
solo |
|||
disabled |
|||
hide-details |
|||
) |
|||
|
|||
v-dialog(lazy, v-model='dateActivator', width='290px', ref='dateDialog') |
|||
v-date-picker(v-model='item.value', scrollable, color='primary') |
|||
v-btn(flat, color='primary' @click='$refs.dateDialog.save(date)', block) ok |
|||
|
|||
v-dialog(lazy, v-model='timeActivator', width='300px', ref='timeDialog') |
|||
v-time-picker(v-model='item.value', scrollable, color='primary') |
|||
v-btn(flat, color='primary' @click='$refs.timeDialog.save(time)', block) ok |
|||
|
|||
v-btn(icon, @click='remove'): v-icon(color='blue-grey') clear |
|||
</template> |
|||
|
|||
<script> |
|||
import _ from 'lodash' |
|||
|
|||
// import countriesQuery from 'gql/upsells-query-countries.gql' |
|||
|
|||
export default { |
|||
inject: ['allowedCriteriaTypes'], |
|||
props: { |
|||
value: { |
|||
type: Object, |
|||
default() { return {} } |
|||
}, |
|||
groupIndex: { |
|||
type: Number, |
|||
default() { return 0 } |
|||
}, |
|||
itemIndex: { |
|||
type: Number, |
|||
default() { return 0 } |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
item: { |
|||
operator: '', |
|||
type: '', |
|||
value: '' |
|||
}, |
|||
dateActivator: false, |
|||
dateDialog: false, |
|||
timeActivator: false, |
|||
timeDialog: false, |
|||
countries: [], |
|||
groups: [], |
|||
criteriaTypes: [ |
|||
{ text: 'Path', value: 'path', icon: 'space_bar', color: 'blue', description: 'Match the path of the document being viewed.' }, |
|||
{ text: 'Date', value: 'date', icon: 'date_range', color: 'blue', description: 'Match the current calendar day.' }, |
|||
{ text: 'Time', value: 'time', icon: 'access_time', color: 'blue', description: 'Match the current time of day.' }, |
|||
{ text: 'User Country', value: 'country', icon: 'public', color: 'red', description: `Match the user's country.` }, |
|||
{ text: 'User Group', value: 'group', icon: 'group', color: 'orange', description: 'Match the user group assignments.' } |
|||
], |
|||
criteriaOperators: { |
|||
country: [ |
|||
{ text: 'In', value: 'in', icon: '[...]' }, |
|||
{ text: 'Not In', value: 'notIn', icon: '[ x ]' } |
|||
], |
|||
path: [ |
|||
{ text: 'Matches Exactly', value: 'eq', icon: '=' }, |
|||
{ text: 'NOT Matches Exactly', value: 'ne', icon: '!=' }, |
|||
{ text: 'Starts With', value: 'sw', icon: 'x...' }, |
|||
{ text: 'NOT Starts With', value: 'nsw', icon: '!x...' }, |
|||
{ text: 'Ends With', value: 'ew', icon: '...x' }, |
|||
{ text: 'NOT Ends With', value: 'new', icon: '!...x' }, |
|||
{ text: 'Matches Regex', value: 'regexp', icon: '^x$' } |
|||
], |
|||
date: [ |
|||
{ text: 'On or After', value: 'gte', icon: '>=' }, |
|||
{ text: 'On or Before', value: 'lte', icon: '<=' } |
|||
], |
|||
time: [ |
|||
{ text: 'At or Later Than', value: 'gte', icon: '>=' }, |
|||
{ text: 'At or Before', value: 'lte', icon: '<=' } |
|||
], |
|||
group: [ |
|||
{ text: 'Is Part Of', value: 'in', icon: '[...]' }, |
|||
{ text: 'Is Not Part Of', value: 'notIn', icon: '[ x ]' } |
|||
] |
|||
} |
|||
} |
|||
}, |
|||
computed: { |
|||
filteredCriteriaOperators() { |
|||
return _.get(this.criteriaOperators, this.item.type, []) |
|||
}, |
|||
filteredCriteriaTypes() { |
|||
console.info(this.allowedCriteriaTypes) |
|||
return _.filter(this.criteriaTypes, c => _.includes(this.allowedCriteriaTypes, c.value)) |
|||
}, |
|||
itemType() { |
|||
return this.item.type |
|||
} |
|||
}, |
|||
watch: { |
|||
itemType(newValue, oldValue) { |
|||
this.item.operator = _.head(this.criteriaOperators[newValue]).value |
|||
this.item.value = '' |
|||
}, |
|||
item: { |
|||
handler(newValue, oldValue) { |
|||
this.$emit('update', this.groupIndex, this.itemIndex, this.item) |
|||
}, |
|||
deep: true |
|||
} |
|||
}, |
|||
mounted() { |
|||
if (!this.item.type) { |
|||
this.$refs.typeSelect.showMenu() |
|||
} |
|||
}, |
|||
methods: { |
|||
remove() { |
|||
this.$emit('remove', this.groupIndex, this.itemIndex) |
|||
} |
|||
} |
|||
// apollo: { |
|||
// countries: { |
|||
// query: countriesQuery, |
|||
// update: (data) => data.location.countries |
|||
// } |
|||
// } |
|||
} |
|||
</script> |
@ -1,173 +0,0 @@ |
|||
<template lang="pug"> |
|||
.criterias |
|||
transition-group(name='criterias-group', tag='div') |
|||
.criterias-group(v-for='(group, g) in groups', :key='g') |
|||
transition-group(name='criterias-item', tag='div') |
|||
criterias-item(v-for='(item, i) in group', :key='i', :item='item', :group-index='g', :item-index='i', @update='updateItem', @remove='removeItem') |
|||
.criterias-item-more |
|||
v-btn.ml-0(@click='addItem(group)', small, color='blue-grey lighten-2', dark, depressed) |
|||
v-icon(color='white', left) add |
|||
| Add condition |
|||
.criterias-group-more |
|||
v-btn(@click='addGroup', small, color='blue-grey lighten-1', dark, depressed) |
|||
v-icon(color='white', left) add |
|||
| Add condition group |
|||
</template> |
|||
|
|||
<script> |
|||
import CriteriasItem from './criterias-item.vue' |
|||
|
|||
export default { |
|||
components: { |
|||
CriteriasItem |
|||
}, |
|||
props: { |
|||
value: { |
|||
type: Array, |
|||
default() { return [] } |
|||
}, |
|||
types: { |
|||
type: Array, |
|||
default() { |
|||
return ['country', 'path', 'date', 'time', 'group'] |
|||
} |
|||
} |
|||
}, |
|||
provide () { |
|||
return { |
|||
allowedCriteriaTypes: this.types |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
dataGroups: this.value || [] |
|||
} |
|||
}, |
|||
computed: { |
|||
groups: { |
|||
get() { return this.dataGroups }, |
|||
set(grp) { |
|||
this.dataGroups = grp |
|||
} |
|||
} |
|||
}, |
|||
watch: { |
|||
dataGroups(newValue, oldValue) { |
|||
if (newValue !== oldValue) { |
|||
this.$emit('input', newValue) |
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
addGroup() { |
|||
this.dataGroups.push([{}]) |
|||
}, |
|||
addItem(group) { |
|||
group.push({}) |
|||
}, |
|||
updateItem(groupIndex, itemIndex, item) { |
|||
console.info(item) |
|||
this.$set(this.dataGroups[groupIndex], itemIndex, item) |
|||
}, |
|||
removeItem(groupIndex, itemIndex) { |
|||
this.dataGroups[groupIndex].splice(itemIndex, 1) |
|||
if (this.dataGroups[groupIndex].length < 1) { |
|||
this.dataGroups.splice(groupIndex, 1) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.criterias { |
|||
&-group { |
|||
background-color: mc('blue-grey', '100'); |
|||
border-radius: 4px; |
|||
padding: 1rem; |
|||
position: relative; |
|||
|
|||
&-enter-active, &-leave-active { |
|||
transition: all .5s ease; |
|||
} |
|||
&-enter, &-leave-to { |
|||
opacity: 0; |
|||
} |
|||
|
|||
& + .criterias-group { |
|||
margin-top: 1rem; |
|||
|
|||
&::before { |
|||
content: 'OR'; |
|||
position: absolute; |
|||
display: inline-flex; |
|||
padding: 0 2rem; |
|||
top: -1.25rem; |
|||
left: 2rem; |
|||
background-color: mc('blue-grey', '100'); |
|||
color: mc('blue-grey', '700'); |
|||
font-weight: 600; |
|||
font-size: .9rem; |
|||
} |
|||
} |
|||
|
|||
&-more { |
|||
margin: .5rem 0 0 .4rem; |
|||
} |
|||
} |
|||
|
|||
&-item { |
|||
display: flex; |
|||
background-color: mc('blue-grey', '200'); |
|||
border-radius: 4px; |
|||
padding: .5rem; |
|||
|
|||
&-enter-active, &-leave-active { |
|||
transition: all .5s ease; |
|||
} |
|||
&-enter, &-leave-to { |
|||
opacity: 0; |
|||
} |
|||
|
|||
& + .criterias-item { |
|||
margin-top: .5rem; |
|||
position: relative; |
|||
|
|||
&::before { |
|||
content: 'AND'; |
|||
position: absolute; |
|||
width: 2rem; |
|||
height: 2rem; |
|||
border-radius: 50%; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
font-weight: 600; |
|||
color: mc('blue-grey', '700'); |
|||
font-size: .7rem; |
|||
background-color: mc('blue-grey', '100'); |
|||
left: -2rem; |
|||
top: -1.3rem; |
|||
} |
|||
} |
|||
|
|||
.input-group { |
|||
&:nth-child(1) { |
|||
flex: 0 1 350px; |
|||
} |
|||
|
|||
&:nth-child(2) { |
|||
flex: 0 1 250px; |
|||
} |
|||
|
|||
& + * { |
|||
margin-left: .5rem; |
|||
} |
|||
} |
|||
|
|||
&-more { |
|||
margin-top: .15rem; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,4 @@ |
|||
<?xml version="1.0"?> |
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24px" height="24px"> |
|||
<path style="fill:#ffffff;" d="M 16.125 1 C 14.972 1.067 13.648328 1.7093438 12.861328 2.5273438 C 12.150328 3.2713438 11.589359 4.3763125 11.818359 5.4453125 C 13.071359 5.4783125 14.329031 4.8193281 15.082031 3.9863281 C 15.785031 3.2073281 16.318 2.12 16.125 1 z M 16.193359 5.4433594 C 14.384359 5.4433594 13.628 6.5546875 12.375 6.5546875 C 11.086 6.5546875 9.9076562 5.5136719 8.3476562 5.5136719 C 6.2256562 5.5146719 3 7.4803281 3 12.111328 C 3 16.324328 6.8176563 21 8.9726562 21 C 10.281656 21.013 10.599 20.176969 12.375 20.167969 C 14.153 20.154969 14.536656 21.011 15.847656 21 C 17.323656 20.989 18.476359 19.367031 19.318359 18.082031 C 19.922359 17.162031 20.170672 16.692344 20.638672 15.652344 C 17.165672 14.772344 16.474672 9.1716719 20.638672 8.0136719 C 19.852672 6.6726719 17.558359 5.4433594 16.193359 5.4433594 z"/> |
|||
</svg> |
@ -0,0 +1,13 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> |
|||
<svg width="100%" height="100%" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"> |
|||
<g> |
|||
<path d="M3.929,43.929c3.902,-3.903 10.239,-3.903 14.142,0c3.902,3.902 3.902,10.239 0,14.142c-3.903,3.902 -10.24,3.902 -14.142,0c-3.903,-3.903 -3.903,-10.24 0,-14.142Z" style="fill:#ff5576;"/> |
|||
<path d="M7.5,56c-0.4,0 -0.75,-0.15 -1.05,-0.45c-0.6,-0.6 -0.6,-1.55 0,-2.1l7,-7c0.6,-0.6 1.55,-0.6 2.1,0c0.6,0.6 0.6,1.55 0,2.1l-7,7c-0.3,0.3 -0.65,0.45 -1.05,0.45Z" style="fill:#fff;fill-rule:nonzero;"/> |
|||
<path d="M14.5,56c-0.4,0 -0.75,-0.15 -1.05,-0.45l-7,-7c-0.6,-0.6 -0.6,-1.55 0,-2.1c0.6,-0.6 1.55,-0.6 2.1,0l7,7c0.6,0.6 0.6,1.55 0,2.1c-0.3,0.3 -0.65,0.45 -1.05,0.45Z" style="fill:#fff;fill-rule:nonzero;"/> |
|||
</g> |
|||
<g> |
|||
<path d="M53,19.5c-0.85,0 -1.5,0.65 -1.5,1.5l-0.05,33.5c0,1.95 -1.55,3.5 -3.5,3.5l-21.95,0c-0.85,0 -1.5,0.65 -1.5,1.5c0,0.85 0.65,1.5 1.5,1.5l21.95,0c3.6,0 6.5,-2.9 6.5,-6.5l0.05,-33.5c0,-0.85 -0.7,-1.5 -1.5,-1.5Z" style="fill:#fff;fill-rule:nonzero;"/> |
|||
<path d="M51.15,6.4c-2.2,-2.2 -5.05,-3.4 -8.15,-3.4l-27,0c-3.6,0 -6.5,2.9 -6.5,6.5l0,24c0,0.85 0.65,1.5 1.5,1.5c0.85,0 1.5,-0.65 1.5,-1.5l0,-24c0,-1.95 1.55,-3.5 3.5,-3.5l25.5,0l0,3.5c0,3.6 2.9,6.5 6.5,6.5l5,0c0.6,0 1.15,-0.4 1.4,-0.9c0.1,-0.2 0.15,-0.4 0.15,-0.6c0,-0.05 0,-0.1 0,-0.2c-0.1,-3 -1.3,-5.8 -3.4,-7.9Zm-6.65,3.1l0,-3.35c1.7,0.3 3.25,1.1 4.5,2.35c1.25,1.25 2.05,2.8 2.35,4.5l-3.35,0c-1.95,0 -3.5,-1.55 -3.5,-3.5Z" style="fill:#fff;fill-rule:nonzero;"/> |
|||
</g> |
|||
</svg> |
@ -0,0 +1,4 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24" version="1.1" width="24px" height="24px"> |
|||
<path style="fill:#ffffff;" d="M 13 1 L 13 4 L 16 4 L 16 1 Z M 5 5 L 5 8 L 8 8 L 8 5 Z M 9 5 L 9 8 L 12 8 L 12 5 Z M 13 5 L 13 8 L 16 8 L 16 5 Z M 18.3125 7.84375 C 17.9375 7.878906 17.289063 8.507813 17 9.03125 C 16.269531 10.339844 16.828125 11.988281 16.96875 12.34375 C 16.644531 12.761719 15 13 15 13 L 0.96875 13 C 0.148438 13.027344 0 14.246094 0 14.53125 C -0.0351563 19.5 3.710938 21.988281 7.96875 22 C 14.132813 22.019531 17.871094 19.5625 20.03125 16 L 23 16 C 22.492188 15.871094 21.820313 15.660156 22 15 C 21.800781 15.292969 21.09375 15.582031 20.25 15.625 C 20.335938 15.476563 20.421875 15.339844 20.5 15.1875 C 21.824219 15.109375 22.585938 14.488281 23.15625 13.9375 C 23.808594 13.308594 23.960938 12.953125 24 12.59375 C 24.0625 12.050781 22.617188 11.113281 20.84375 10.90625 C 20.675781 9.261719 18.871094 7.789063 18.3125 7.84375 Z M 1 9 L 1 12 L 4 12 L 4 9 Z M 5 9 L 5 12 L 8 12 L 8 9 Z M 9 9 L 9 12 L 12 12 L 12 9 Z M 13 9 L 13 12 L 16 12 L 16 9 Z M 18.4375 9.9375 C 18.726563 10.261719 19.3125 10.992188 19.4375 11.65625 C 19.519531 12.089844 20.121094 12.429688 20.5625 12.46875 C 21.25 12.53125 21.671875 12.664063 22.0625 12.78125 C 21.933594 13.027344 21.054688 13.550781 19.78125 13.5 C 19.441406 13.484375 19.128906 13.6875 19 14 C 18.921875 14.199219 18.632813 14.632813 18.21875 15.15625 C 18.132813 15.105469 18.050781 15.058594 17.96875 15 C 17.515625 15.425781 15.355469 16.308594 13.96875 15 C 13.1875 15.917969 10.75 15.917969 9.96875 15 C 9.714844 15.703125 6.59375 15.902344 5.96875 15 C 5.792969 15.8125 2.992188 16.199219 1.96875 15 L 1.96875 15.5 C 1.949219 15.328125 1.945313 15.15625 1.96875 15 C 1.96875 15 4.289063 15 5.96875 15 C 7.648438 15 8.082031 15 9.96875 15 C 11.855469 15 13.339844 15.003906 13.96875 15 C 14.132813 15 14.984375 15 15 15 C 17.03125 14.875 18.011719 13.761719 18.34375 13.5 C 18.597656 13.300781 18.851563 12.785156 18.625 12.40625 C 18.609375 12.378906 18.003906 10.660156 18.4375 9.9375 Z M 2.0625 16 L 17.46875 16 C 15.738281 17.8125 12.570313 20.101563 7.96875 20 C 6.574219 19.96875 5.101563 19.753906 4.09375 18.96875 C 5.792969 18.910156 7.28125 18.59375 7.28125 18.59375 C 7.714844 18.511719 7.988281 18.089844 7.90625 17.65625 C 7.824219 17.222656 7.402344 16.917969 6.96875 17 C 6.933594 17.007813 4.667969 17.5625 2.59375 17.3125 C 2.476563 17.097656 2.21875 16.570313 2.0625 16 Z M 8.4375 17 C 8.179688 17 7.96875 17.210938 7.96875 17.46875 C 7.96875 17.726563 8.179688 17.9375 8.4375 17.9375 C 8.695313 17.9375 8.90625 17.726563 8.90625 17.46875 C 8.90625 17.40625 8.898438 17.367188 8.875 17.3125 C 8.84375 17.371094 8.757813 17.40625 8.6875 17.40625 C 8.582031 17.40625 8.53125 17.292969 8.53125 17.1875 C 8.53125 17.117188 8.535156 17.09375 8.59375 17.0625 C 8.542969 17.042969 8.496094 17 8.4375 17 Z "/> |
|||
</svg> |
@ -0,0 +1,4 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24" version="1.1" width="24px" height="24px"> |
|||
<path style="fill:#ffffff;" d="M 10.4375 2 C 6.140625 2 3 4.824219 3 11 C 3 14.410156 4.773438 20.515625 2 22 L 4.3125 22 C 5.203125 20.640625 5.09375 18.6875 5.09375 18.6875 C 5.09375 18.6875 4.03125 17.234375 4.03125 16.46875 C 4.03125 15.0625 5.15625 14.3125 5.15625 14.3125 C 5.15625 14.3125 4.09375 13.304688 4.09375 11.5625 C 4.09375 10.054688 5.296875 9.375 5.90625 9.375 C 8.144531 9.375 8.25 12 8.25 12 L 10.375 12 C 10.375 12 10.238281 9.125 12.96875 9.125 C 13.890625 9.125 15.46875 9.933594 15.46875 12.0625 C 15.46875 13.261719 15.09375 14 15.09375 14 C 15.09375 14 16.46875 14.734375 16.46875 16.03125 C 16.46875 17.285156 15.53125 18.34375 15.53125 18.34375 L 17.09375 22 L 22 22 C 22 22 19 20.789063 19 11 C 19 10.253906 19.222656 2 10.4375 2 Z M 13.75 4.03125 C 14.003906 4.027344 14.289063 4.109375 14.5625 4.28125 C 15.109375 4.628906 15.386719 5.203125 15.15625 5.5625 C 14.925781 5.921875 14.296875 5.941406 13.75 5.59375 C 13.203125 5.246094 12.925781 4.671875 13.15625 4.3125 C 13.269531 4.132813 13.496094 4.035156 13.75 4.03125 Z M 6.125 11 C 5.617188 11 5.03125 11.367188 5.03125 12.46875 C 5.03125 13.453125 6.3125 14.34375 6.3125 14.34375 C 6.3125 14.34375 4.5625 15.175781 4.5625 16.5 C 4.5625 17.226563 5.316406 17.96875 6.0625 18.5625 C 6.800781 19.167969 7.738281 20.21875 9 20.21875 C 10.796875 20.21875 12.292969 18.859375 13.09375 18.375 C 13.894531 17.890625 15.5 17.109375 15.5 16 C 15.5 14.671875 13.03125 14.28125 13.03125 14.28125 C 13.03125 14.28125 14.25 13.890625 14.25 12.59375 C 14.25 11.679688 13.65625 11 12.90625 11 C 11.820313 11 11.53125 12.046875 11.53125 12.59375 C 11.53125 13.210938 11.78125 13.8125 11.78125 13.8125 C 11.78125 13.8125 10.46875 13.03125 9 13.03125 C 8.214844 13.03125 7.34375 13.5625 7.34375 13.5625 C 7.34375 13.5625 7.4375 13.128906 7.4375 12.65625 C 7.4375 12.175781 7.15625 11 6.125 11 Z M 8.28125 13.75 C 8.546875 13.703125 8.25 14.203125 7.9375 14.53125 C 7.816406 14.65625 7.40625 14.277344 7.4375 14.1875 C 7.480469 14.09375 7.878906 13.835938 8.28125 13.75 Z M 9.71875 13.75 C 9.917969 13.75 10.339844 13.851563 10.5625 13.96875 C 10.730469 14.058594 10.699219 14.539063 10.53125 14.625 C 10.3125 14.734375 9.625 13.96875 9.625 13.78125 C 9.625 13.75 9.652344 13.75 9.71875 13.75 Z M 14.5 16 C 14.5 16 11.46875 19 9 19 C 6.890625 19 5.0625 16.71875 5.0625 16.71875 C 5.0625 16.71875 7.140625 18 9 18 C 11.125 18 14.5 16 14.5 16 Z "/> |
|||
</svg> |
@ -0,0 +1,4 @@ |
|||
<?xml version="1.0"?> |
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24px" height="24px"> |
|||
<path style="fill:#ffffff;" d="M 21 2 L 12 3.5 L 12 11 L 21 11 L 21 2 z M 10 3.8320312 L 3 5 L 3 11 L 10 11 L 10 3.8320312 z M 3 13 L 3 19 L 10 20.167969 L 10 13 L 3 13 z M 12 13 L 12 20.5 L 21 22 L 21 13 L 12 13 z"/> |
|||
</svg> |
@ -0,0 +1,35 @@ |
|||
const { Client } = require('pg') |
|||
const fs = require('fs') |
|||
const path = require('path') |
|||
const yaml = require('js-yaml') |
|||
|
|||
let config = {} |
|||
|
|||
try { |
|||
conf = yaml.safeLoad( |
|||
cfgHelper.parseConfigValue( |
|||
fs.readFileSync(path.join(process.cwd(), 'dev/docker/config.yml'), 'utf8') |
|||
) |
|||
) |
|||
} catch (err) { |
|||
console.error(err.message) |
|||
process.exit(1) |
|||
} |
|||
|
|||
const client = new Client({ |
|||
user: config.db.username, |
|||
host: config.db.host, |
|||
database: config.db.database, |
|||
password: config.db.password, |
|||
port: config.db.port, |
|||
}) |
|||
|
|||
async function main () { |
|||
await client.connect() |
|||
await client.query('DROP SCHEMA public CASCADE;') |
|||
await client.query('CREATE SCHEMA public;') |
|||
await client.end() |
|||
console.info('Success.') |
|||
} |
|||
|
|||
main() |
Write
Preview
Loading…
Cancel
Save