mirror of
https://github.com/fleetdm/fleet
synced 2026-04-21 13:37:30 +00:00
Changes:
- Updated the configuration profile builder to support Windows settings
that have a templated setting target (e.g.,
`./Device/Vendor/MSFT/WiFi/Profile/{SSID}/WlanXml`)
- Updated the configuration profile builder to include Wi-fi settings
for Windows devices.
372 lines
28 KiB
Text
Vendored
372 lines
28 KiB
Text
Vendored
<div id="configuration-builder" v-cloak>
|
|
<div class="d-lg-block d-none">
|
|
<div class="header" purpose="header-container" hide-when-scrolled data-nosnippet>
|
|
<div purpose="header-background">
|
|
<div purpose="configuration-builder-header">
|
|
<div purpose="page-header" class="container-fluid d-flex justify-content-start align-items-center">
|
|
<a purpose="header-logo" href="/">
|
|
<img alt="Fleet logo" src="/images/logo-blue-118x41@2x.png"/>
|
|
</a>
|
|
<!-- <div purpose="search-bar" v-if="step === 'configuration-builder'">
|
|
<div purpose="disabled-search" class="d-flex w-100">
|
|
<div class="input-group">
|
|
<div class="input-group-prepend">
|
|
<span class="input-group-text border-0 bg-transparent pl-3" >
|
|
<img style="height: 16px; width: 16px;" class="search" alt="search" src="/images/icon-search-16x16@2x.png">
|
|
</span>
|
|
</div>
|
|
<div class="form-control border-0 ">
|
|
<input class="docsearch-input pr-1"
|
|
placeholder="Search" aria-label="Search"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div purpose="search-results">
|
|
|
|
</div>
|
|
</div> -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div purpose="page-container" class="container-fluid px-0">
|
|
<%
|
|
//
|
|
// ╔═╗╦ ╔═╗╔╦╗╔═╗╔═╗╦═╗╔╦╗ ╔═╗╔═╗╦ ╔═╗╔═╗╔╦╗╔═╗╦═╗
|
|
// ╠═╝║ ╠═╣ ║ ╠╣ ║ ║╠╦╝║║║ ╚═╗║╣ ║ ║╣ ║ ║ ║ ║╠╦╝
|
|
// ╩ ╩═╝╩ ╩ ╩ ╚ ╚═╝╩╚═╩ ╩ ╚═╝╚═╝╩═╝╚═╝╚═╝ ╩ ╚═╝╩╚═
|
|
%>
|
|
<div purpose="platform-selector-step" v-if="step === 'platform-select'">
|
|
<div purpose="platform-selector" class="mx-auto my-auto">
|
|
<h2>Create a new configuration profile</h2>
|
|
<p class="mb-0">Choose an operating system to continue.</p>
|
|
<ajax-form :handle-submitting="handleSubmittingPlatformSelectForm" :form-errors.sync="formErrors" :form-data="platformSelectFormData" :form-rules="platformSelectFormRules" :syncing.sync="syncing" :cloud-error.sync="cloudError">
|
|
<div purpose="platforms" id="platform" class="d-flex flex-row">
|
|
<div purpose="platform-button" :class="[formErrors.platform ? 'is-invalid' : platformSelectFormData.platform === 'macos' ? 'selected' : '' ]" style="margin-right: 10px;" @click="platformSelectFormData.platform = 'macos'">
|
|
<img src="/images/os-macos-dark-24x24@2x.png" alt="macOS" class="d-inline">
|
|
macOS
|
|
</div>
|
|
<div purpose="platform-button" :class="[formErrors.platform ? 'is-invalid' : platformSelectFormData.platform === 'windows' ? 'selected' : '' ]" @click="platformSelectFormData.platform = 'windows'">
|
|
<img src="/images/os-windows-dark-24x24@2x.png" alt="Windows" class="d-inline">
|
|
Windows
|
|
</div>
|
|
</div>
|
|
<div class="invalid-feedback" v-if="formErrors.platform">Please select an option</div>
|
|
<ajax-button type="submit" purpose="submit-button" class="btn btn-primary" :syncing="syncing" v-if="platformSelectFormData.platform">Create</ajax-button>
|
|
</ajax-form>
|
|
</div>
|
|
</div>
|
|
<%
|
|
//
|
|
// ╔═╗╔═╗╔╗╔╔═╗╦╔═╗╦ ╦╦═╗╔═╗╔╦╗╦╔═╗╔╗╔ ╔╗ ╦ ╦╦╦ ╔╦╗╔═╗╦═╗
|
|
// ║ ║ ║║║║╠╣ ║║ ╦║ ║╠╦╝╠═╣ ║ ║║ ║║║║ ╠╩╗║ ║║║ ║║║╣ ╠╦╝
|
|
// ╚═╝╚═╝╝╚╝╚ ╩╚═╝╚═╝╩╚═╩ ╩ ╩ ╩╚═╝╝╚╝ ╚═╝╚═╝╩╩═╝═╩╝╚═╝╩╚═
|
|
%>
|
|
<div purpose="platform-selector-step" v-if="step === 'configuration-builder'">
|
|
<%
|
|
//
|
|
// ╔═╗╔═╗╔╦╗╔═╗╔═╗╔═╗╦═╗╦ ╦ ╔═╗╔═╗╦ ╔═╗╔═╗╔╦╗╔═╗╦═╗
|
|
// ║ ╠═╣ ║ ║╣ ║ ╦║ ║╠╦╝╚╦╝ ╚═╗║╣ ║ ║╣ ║ ║ ║ ║╠╦╝
|
|
// ╚═╝╩ ╩ ╩ ╚═╝╚═╝╚═╝╩╚═ ╩ ╚═╝╚═╝╩═╝╚═╝╚═╝ ╩ ╚═╝╩╚═
|
|
%>
|
|
<div purpose="category-selector" >
|
|
<div purpose="category-options" v-if="selectedPlatform === 'windows'">
|
|
<div v-for="category in windowsCategoriesAndPayloads">
|
|
<a @click="clickExpandCategory(category.categorySlug)" :class="[expandedCategory === category.categorySlug ? 'selected' : '' ]" >{{category.categoryName}}</a>
|
|
|
|
<div purpose="subcategories" v-if="expandedCategory === category.categorySlug">
|
|
<a @click="clickSelectPayloadCategory(subcategory)" v-for="subcategory in category.subcategories">{{subcategory.subcategoryName}}</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div purpose="category-options" v-if="selectedPlatform === 'macos'">
|
|
<div v-for="category in macosCategoriesAndPayloads">
|
|
<a @click="clickExpandCategory(category.categorySlug)" :class="[expandedCategory === category.categorySlug ? 'selected' : '' ]" >{{category.categoryName}}</a>
|
|
<div purpose="subcategories" v-if="expandedCategory === category.categorySlug">
|
|
<a @click="clickSelectPayloadCategory(subcategory)" v-for="subcategory in category.subcategories">{{subcategory.subcategoryName}}</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<%
|
|
//
|
|
// ╔═╗╔═╗╔╦╗╦╔═╗╔╗╔ ╔═╗╔═╗╦ ╔═╗╔═╗╔╦╗╔═╗╦═╗
|
|
// ║ ║╠═╝ ║ ║║ ║║║║ ╚═╗║╣ ║ ║╣ ║ ║ ║ ║╠╦╝
|
|
// ╚═╝╩ ╩ ╩╚═╝╝╚╝ ╚═╝╚═╝╩═╝╚═╝╚═╝ ╩ ╚═╝╩╚═
|
|
%>
|
|
<div purpose="selected-subcategory-and-options">
|
|
<div purpose="selected-subcategory" :class="[selectedPayloadCategory ? 'slide-in' : '' ]">
|
|
<div v-if="selectedPayloadCategory">
|
|
<div purpose="subcategory-header">
|
|
<h2>{{selectedPayloadCategory.subcategoryName}}</h2>
|
|
<p class="mb-0">
|
|
{{selectedPayloadCategory.description}} <a target="_blank" :href="selectedPayloadCategory.learnMoreLinkUrl" v-if="selectedPayloadCategory.learnMoreLinkUrl">Learn more</a>
|
|
</p>
|
|
<div purpose="fleet-note" v-if="selectedPayloadCategory.noteForFleetUsers">
|
|
<p>
|
|
<strong>For Fleet Users:</strong> {{selectedPayloadCategory.noteForFleetUsers}}
|
|
<a :href="selectedPayloadCategory.docsLinkForFleetUsers" target="_blank" v-if="selectedPayloadCategory.docsLinkForFleetUsers">Docs</a>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div purpose="subcategory-options" v-if="_.keysIn(selectedPayloadCategory.payloads[0]).includes('payloadGroup')">
|
|
<div purpose="payload-group" v-for="(group, groupName) in _.groupBy(selectedPayloadCategory.payloads, 'payloadGroup')">
|
|
<p><strong>{{groupName}}</strong></p>
|
|
<div purpose="option" v-for="payload in group">
|
|
<label :for="payload.uniqueSlug">
|
|
<span purpose="custom-checkbox" :class="[selectedPayloadSettings[payload.uniqueSlug] ? 'checked' : '']" ><span purpose="custom-checkbox-check"></span></span>
|
|
<input type="checkbox" v-model="selectedPayloadSettings[payload.uniqueSlug]" :id="payload.uniqueSlug" @input="clickSelectPayload(payload.uniqueSlug)">
|
|
{{payload.name}}
|
|
<img style="margin-left: 6px; height: 14px" class="d-inline" purpose="tooltip-icon" src="/images/icon-more-info-14x14@2x.png" alt="More info" data-toggle="tooltip" tabindex="0" data-placement="top" :title="payload.tooltip" v-if="payload.tooltip">
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div purpose="subcategory-options" v-else>
|
|
<div purpose="option" v-for="payload in selectedPayloadCategory.payloads">
|
|
|
|
<label :for="payload.uniqueSlug">
|
|
<span purpose="custom-checkbox" :class="[selectedPayloadSettings[payload.uniqueSlug] ? 'checked' : '']" ><span purpose="custom-checkbox-check"></span></span>
|
|
<input type="checkbox" v-model="selectedPayloadSettings[payload.uniqueSlug]" :id="payload.uniqueSlug" @input="clickSelectPayload(payload.uniqueSlug)">
|
|
{{payload.name}}
|
|
<img style="margin-left: 6px; height: 14px" class="d-inline" purpose="tooltip-icon" src="/images/icon-more-info-14x14@2x.png" alt="More info" data-toggle="tooltip" tabindex="0" data-placement="top" :title="payload.tooltip" v-if="payload.tooltip">
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<%
|
|
//
|
|
// ╔═╗╔═╗╦ ╦╦ ╔═╗╔═╗╔╦╗ ╔═╗╔═╗╔╦╗╦╔═╗╔╗╔╔═╗
|
|
// ╠═╝╠═╣╚╦╝║ ║ ║╠═╣ ║║ ║ ║╠═╝ ║ ║║ ║║║║╚═╗
|
|
// ╩ ╩ ╩ ╩ ╩═╝╚═╝╩ ╩═╩╝ ╚═╝╩ ╩ ╩╚═╝╝╚╝╚═╝
|
|
%>
|
|
<div purpose="payload-options">
|
|
<ajax-form :handle-submitting="handleSubmittingConfigurationBuilderForm" :form-errors.sync="formErrors" :form-data="configurationBuilderFormData" :form-rules="configurationBuilderFormRules" :syncing.sync="syncing" :cloud-error.sync="cloudError">
|
|
<div purpose="options-container" :class="[selectedPayloads.length > 0 ? 'slide-in' : '' ]">
|
|
<div purpose="payload-category" v-for="category in _.keysIn(selectedPayloadsGroupedByCategory)">
|
|
<ajax-form :handle-submitting="handleSubmittingSinglePayloadConfigurationBuilderForm" :form-errors.sync="formErrors" :form-data="configurationBuilderFormData" :form-rules="configurationBuilderByCategoryFormRules[category]" :syncing.sync="syncing" :cloud-error.sync="cloudError">
|
|
<div purpose="category-header">
|
|
<h2 class="mb-0">{{category}}</h2>
|
|
<div purpose="download-and-remove-buttons">
|
|
<a purpose="remove-button" @click="clickRemoveOneCategoryPayloadOptions(category)">Remove all</a>
|
|
<ajax-button purpose="download-button" :syncing="syncing" @click="clickSetCurrentSelectedCategory(category)"><img alt="download" src="/images/icon-download.png" style="height: 12px;"></ajax-button>
|
|
</div>
|
|
</div>
|
|
|
|
<div purpose="payload-option" v-for="option in selectedPayloadsGroupedByCategory[category]">
|
|
<div purpose="name-and-access-type" class="d-flex flex-row align-items-center justify-content-between w-100">
|
|
<p class="mb-0"><strong>{{option.name}}</strong></p>
|
|
<div class="d-flex flex-column" v-if="selectedPlatform === 'windows'">
|
|
<select :class="[formErrors[option.uniqueSlug+'-access-type'] ? 'is-invalid' : '']" purpose="access-type-select" v-model.trim="configurationBuilderFormData[option.uniqueSlug+'-access-type']" class="form-control" style="width: 120px">
|
|
<option selected value="undefined" >Access type</option>
|
|
<option :value="accessType" style="text-transform: uppercase;" v-for="accessType in option.supportedAccessTypes">{{accessType}}</option>
|
|
</select>
|
|
<div class="invalid-feedback" v-if="formErrors[option.uniqueSlug+'-access-type']">Please select an<br> access type</div>
|
|
</div>
|
|
</div>
|
|
<% // Number input %>
|
|
<div purpose="option-value" v-if="['number'].includes(option.formInput.type)">
|
|
<div class="d-flex flex-row align-items-center">
|
|
<input :class="[formErrors[option.uniqueSlug+'-value'] ? 'is-invalid' : '']" class="form-control" v-model.trim="configurationBuilderFormData[option.uniqueSlug+'-value']" :type="option.formInput.type" placeholder="0" :min="option.formInput.minValue" :max="option.formInput.maxValue">
|
|
<span purpose="unit-label" v-if="option.formInput.unitLabel">{{option.formInput.unitLabel}}</span>
|
|
</div>
|
|
<div class="invalid-feedback d-block" v-if="formErrors[option.uniqueSlug+'-value'] && option.formInput.unitLabel">Please enter a number of {{option.formInput.unitLabel}}</div>
|
|
<div class="invalid-feedback d-block" v-else-if="formErrors[option.uniqueSlug+'-value']">Please enter a value</div>
|
|
</div>
|
|
<% // Text input %>
|
|
<div purpose="option-value" v-if="['text'].includes(option.formInput.type)">
|
|
<input :class="[formErrors[option.uniqueSlug+'-value'] ? 'is-invalid' : '']" class="form-control" v-model.trim="configurationBuilderFormData[option.uniqueSlug+'-value']" :type="option.formInput.type" placeholder="Please enter a value" >
|
|
<div class="invalid-feedback" v-if="formErrors[option.uniqueSlug+'-value']">Please enter a value</div>
|
|
</div>
|
|
<% // Radio input %>
|
|
<div purpose="option-value" v-else-if="['radio'].includes(option.formInput.type)" :class="[formErrors[option.uniqueSlug+'-value'] ? 'is-invalid' : '']">
|
|
<label purpose="form-option" class="form-control" :class="[configurationBuilderFormData[option.uniqueSlug+'-value'] === formInput.value ? 'selected' : '']" v-for="formInput of option.formInput.options" @input="clickAutoSelectWhenSet(formInput)">
|
|
<input type="radio" v-model.trim="configurationBuilderFormData[option.uniqueSlug+'-value']" :value="formInput.value" @input="clickClearOneFormError(option.uniqueSlug+'-value')">
|
|
<span purpose="custom-radio"><span purpose="custom-radio-selected"></span></span>
|
|
{{formInput.name}}
|
|
</label>
|
|
<div class="invalid-feedback" v-if="formErrors[option.uniqueSlug+'-value']">Please select an option</div>
|
|
</div>
|
|
<%// Checkbox input %>
|
|
<div purpose="option-value" v-else-if="['boolean'].includes(option.formInput.type)">
|
|
<label purpose="form-option" class="form-control">
|
|
<input type="checkbox" v-model.trim="configurationBuilderFormData[option.uniqueSlug+'-value']" @input="clickClearOneFormError(option.uniqueSlug+'-value')">
|
|
<span purpose="custom-switch" :class="[configurationBuilderFormData[option.uniqueSlug+'-value'] ? 'checked' : '']"><span purpose="custom-switch-status"></span></span>
|
|
{{ configurationBuilderFormData[option.uniqueSlug+'-value'] ? 'Yes' : 'No' }}
|
|
</label>
|
|
</div>
|
|
<%// Select input %>
|
|
<div purpose="option-value" v-else-if="['select'].includes(option.formInput.type)">
|
|
<select :class="[formErrors[option.uniqueSlug+'-value'] ? 'is-invalid' : '']" purpose="access-type-select" v-model.trim="configurationBuilderFormData[option.uniqueSlug+'-value']" class="form-control" style="width: 300px;" @input="clickAutoSelectWhenSet(formInput)">
|
|
<option selected value="undefined" >Select an option</option>
|
|
<option :value="formInput.value" style="text-transform: uppercase;" v-for="formInput in option.formInput.options">{{formInput.name}}</option>
|
|
</select>
|
|
<div class="invalid-feedback" v-if="formErrors[option.uniqueSlug+'-value']">Please select an option</div>
|
|
</div>
|
|
<%// Multiple inputs %>
|
|
<div purpose="option-value" class="w-100" v-else-if="['multifield'].includes(option.formInput.type)">
|
|
<div purpose="multifield-option" v-for="input in option.formInput.inputs">
|
|
<% // Number input %>
|
|
<div purpose="option-value" v-if="['number'].includes(input.type)">
|
|
<div class="d-flex flex-row align-items-center">
|
|
<input :class="[formErrors[option.uniqueSlug+'-'+input.slug] ? 'is-invalid' : '']" class="form-control" v-model.trim="configurationBuilderFormData[option.uniqueSlug+'-'+input.slug]" :type="input.type" placeholder="0" :min="input.minValue" :max="input.maxValue">
|
|
<span purpose="unit-label" v-if="input.unitLabel">{{input.unitLabel}}</span>
|
|
</div>
|
|
<div class="invalid-feedback d-block" v-if="formErrors[option.uniqueSlug+'-'+input.slug] && input.unitLabel">Please enter a number of {{input.unitLabel}}</div>
|
|
<div class="invalid-feedback d-block" v-else-if="formErrors[option.uniqueSlug+'-'+input.slug]">Please enter a value</div>
|
|
</div>
|
|
<% // Text input %>
|
|
<div purpose="option-value" v-if="['text'].includes(input.type)">
|
|
<label>
|
|
<span purpose="nested-label">{{input.name}}</span>
|
|
<input :class="[formErrors[option.uniqueSlug+'-'+input.slug] ? 'is-invalid' : '']" class="form-control" v-model.trim="configurationBuilderFormData[option.uniqueSlug+'-'+input.slug]" :type="input.type" placeholder="Please enter a value" >
|
|
<div class="invalid-feedback" v-if="formErrors[option.uniqueSlug+'-'+input.slug]">Please enter a value</div>
|
|
</label>
|
|
</div>
|
|
<% // Radio input %>
|
|
<div purpose="option-value" v-else-if="['radio'].includes(input.type)" :class="[formErrors[option.uniqueSlug+'-'+input.slug] ? 'is-invalid' : '']">
|
|
<label purpose="form-option" class="form-control" :class="[configurationBuilderFormData[option.uniqueSlug+'-'+input.slug] === formInput.value ? 'selected' : '']" v-for="formInput of input.options">
|
|
<input type="radio" v-model.trim="configurationBuilderFormData[option.uniqueSlug+'-'+input.slug]" :value="formInput.value" @input="clickClearOneFormError(option.uniqueSlug+'-'+input.slug)">
|
|
<span purpose="custom-radio"><span purpose="custom-radio-selected"></span></span>
|
|
{{formInput.name}}
|
|
</label>
|
|
<div class="invalid-feedback" v-if="formErrors[option.uniqueSlug+'-'+input.slug]">Please select an option</div>
|
|
</div>
|
|
<%// Checkbox input %>
|
|
<div purpose="option-value" v-else-if="['boolean'].includes(input.type)">
|
|
<label purpose="form-option" class="form-control">
|
|
<input type="checkbox" v-model.trim="configurationBuilderFormData[option.uniqueSlug+'-'+input.slug]" @input="clickClearOneFormError(option.uniqueSlug+'-'+input.slug)">
|
|
<span purpose="custom-switch" :class="[configurationBuilderFormData[option.uniqueSlug+'-'+input.slug] ? 'checked' : '']"><span purpose="custom-switch-status"></span></span>
|
|
{{ configurationBuilderFormData[option.uniqueSlug+'-'+input.slug] ? 'Yes' : 'No' }}
|
|
</label>
|
|
</div>
|
|
<%// Checkbox (with label) input %>
|
|
<div purpose="option-value" v-else-if="['booleanWithLabel'].includes(input.type)">
|
|
<div class="d-flex flex-row justify-content-between">
|
|
<p>{{input.label}}</p>
|
|
<label purpose="form-option" class="form-control">
|
|
<input type="checkbox" v-model.trim="configurationBuilderFormData[option.uniqueSlug+'-'+input.slug]" @input="clickClearOneFormError(option.uniqueSlug+'-'+input.slug)">
|
|
<span purpose="custom-switch" :class="[configurationBuilderFormData[option.uniqueSlug+'-'+input.slug] ? 'checked' : '']"><span purpose="custom-switch-status"></span></span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<%// select input %>
|
|
<div purpose="option-value" v-else-if="['select'].includes(input.type)">
|
|
<div class="d-flex flex-row justify-content-between">
|
|
<p>{{input.label}}</p>
|
|
<div class="d-flex flex-column" purpose="select-option">
|
|
<select :class="[formErrors[option.uniqueSlug+'-'+input.slug] ? 'is-invalid' : '']" purpose="access-type-select" v-model.trim="configurationBuilderFormData[option.uniqueSlug+'-'+input.slug]" class="form-control">
|
|
<option :value="undefined">Select an option</option>
|
|
<option :value="formInput.value" style="text-transform: uppercase;" v-for="formInput in input.options">{{formInput.name}}</option>
|
|
</select>
|
|
<div class="invalid-feedback" v-if="formErrors[option.uniqueSlug+'-'+input.slug]">Please select<br> an option</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<a @click="clickRemovePayloadOption(option)" purpose="remove-button">Remove</a>
|
|
</div>
|
|
</ajax-form>
|
|
</div>
|
|
</div>
|
|
<div purpose="bottom-download-bar" :class="[ selectedPayloadCategory ? 'slide-in' : '' ]">
|
|
<a purpose="new-button" @click="clickOpenResetFormModal()">Create new</a>
|
|
<ajax-button purpose="download-button" :syncing="syncing" v-if="selectedPayloads.length > 0">Download <img class="d-inline-flex" alt="download" src="/images/icon-download.png" style="height: 12px;"></ajax-button>
|
|
</div>
|
|
</ajax-form>
|
|
|
|
<%// Empty state %>
|
|
<div purpose="empty-state-content" v-if="selectedPayloads.length === 0">
|
|
<div purpose="empty-box">
|
|
</div>
|
|
<p purpose="empty-state-note">
|
|
Choose from the categories on the left to add settings.
|
|
</p>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div purpose="page-container" class="container-fluid px-0 d-flex d-lg-none">
|
|
<div purpose="screen-unsupported" class="mx-auto pt-5 mt-5 text-center d-flex flex-column align-items-center">
|
|
<img style="width: 160px" alt="This screen size not supported." class="mb-3" src="/images/config-editor-small-screen-160x80@2x.png">
|
|
<p class="mb-1">This screen size is not supported yet.</p>
|
|
<p>Please enlarge your browser or try again on a computer.</p>
|
|
</div>
|
|
</div>
|
|
<modal v-if="modal === 'reset-form'" hide-close-button="true" @close="closeModal()">
|
|
<div purpose="reset-form-modal">
|
|
<div purpose="modal-form">
|
|
<h3> Are you sure?</h3>
|
|
<p> Your current profile will be cleared</p>
|
|
|
|
<div purpose="modal-form-buttons">
|
|
<div purpose="modal-button-primary" @click="clickResetForm()">
|
|
I'm sure, create a new profile
|
|
</div>
|
|
<div purpose="modal-button-secondary" @click="modal = undefined">
|
|
No, take me back
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</modal>
|
|
<modal v-if="modal === 'multiple-payloads-selected'" hide-close-button="true" @close="closeModal()">
|
|
<div purpose="multiple-payloads-modal">
|
|
<div purpose="modal-form">
|
|
<h3>Multiple payloads detected</h3>
|
|
<p>To avoid potential conflicts, we recommend downloading each payload individually.</p>
|
|
<p>Are you sure you want to continue?</p>
|
|
|
|
<div purpose="modal-form-buttons">
|
|
<div purpose="modal-button-primary" @click="openDownloadModal()">
|
|
Continue
|
|
</div>
|
|
<div purpose="modal-button-secondary" @click="modal = undefined">
|
|
No, take me back
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</modal>
|
|
<modal v-if="modal === 'download-profile'" hide-close-button="true" @close="closeDownloadModal()">
|
|
<div purpose="download-profile-modal">
|
|
<div purpose="modal-form">
|
|
<h3>Download your configuration file</h3>
|
|
<ajax-form :handle-submitting="handleSubmittingDownloadProfileForm" :form-errors.sync="formErrors" :form-data="downloadProfileFormData" :form-rules="downloadProfileFormRules" :syncing.sync="syncing" :cloud-error.sync="cloudError">
|
|
<div purpose="modal-form-option">
|
|
<label for="profile-name">Profile name <img style="margin-left: 6px; height: 14px" class="d-inline" purpose="tooltip-icon" src="/images/icon-more-info-14x14@2x.png" alt="More info" data-toggle="tooltip" tabindex="0" data-placement="top" title="The name shown to users in their settings. It does not need to be unique."></label>
|
|
<input type="text" :class="[formErrors.name ? 'is-invalid' : '']" class="form-control" id="name" v-model="downloadProfileFormData.name">
|
|
<div class="invalid-feedback">Please enter a name for this profile.</div>
|
|
</div>
|
|
<div purpose="modal-form-option" v-if="selectedPlatform === 'macos'">
|
|
<label for="profile-identifier">Identifier <img style="margin-left: 6px; height: 14px" class="d-inline" purpose="tooltip-icon" src="/images/icon-more-info-14x14@2x.png" alt="More info" data-toggle="tooltip" tabindex="0" data-placement="top" title="A unique reverse-DNS identifier for this payload. It's usually the same as the profile's top-level identifier with an extra part added to describe the specific payload (e.g. .gatekeeper, .wifi). macOS uses it to manage and update individual settings."></label>
|
|
<input type="text" :class="[formErrors.identifier ? 'is-invalid' : '']" class="form-control" id="identifier" v-model="downloadProfileFormData.identifier">
|
|
<div class="invalid-feedback">Please enter a identifier for this profile.</div>
|
|
</div>
|
|
<div purpose="modal-form-option" v-if="selectedPlatform === 'macos'">
|
|
<label for="profile-uuid">UUID <img style="margin-left: 6px; height: 14px" class="d-inline" purpose="tooltip-icon" src="/images/icon-more-info-14x14@2x.png" alt="More info" data-toggle="tooltip" tabindex="0" data-placement="top" title="A unique identifier for this payload, used to track and update the payload during profile replacements. Must be globally unique."></label>
|
|
<input type="text" :class="[formErrors.uuid ? 'is-invalid' : '']" class="form-control" id="uuid" v-model="downloadProfileFormData.uuid">
|
|
<div class="invalid-feedback">Please enter a UUID for this profile.</div>
|
|
</div>
|
|
<div purpose="modal-form-option" v-if="selectedPlatform === 'macos'">
|
|
<label for="profile-description">Description <img style="margin-left: 6px; height: 14px" class="d-inline" purpose="tooltip-icon" src="/images/icon-more-info-14x14@2x.png" alt="More info" data-toggle="tooltip" tabindex="0" data-placement="top" title="A unique identifier for this payload, used to track and update the payload during profile replacements. Must be globally unique."></label>
|
|
<textarea class="form-control" id="description" v-model="downloadProfileFormData.description"></textarea>
|
|
</div>
|
|
<div purpose="modal-form-buttons">
|
|
<ajax-button purpose="download-button" style="max-width: 130px; color: #FFF;" type="submit">
|
|
Download <img alt="download" class="d-inline-flex" src="/images/icon-download.png" style="height: 12px;">
|
|
</ajax-button>
|
|
</div>
|
|
</ajax-form>
|
|
</div>
|
|
</div>
|
|
</modal>
|
|
</div>
|
|
<%- /* Expose server-rendered data as window.SAILS_LOCALS :: */ exposeLocalsToBrowser() %>
|